@dereekb/firebase-server 13.15.0 → 13.17.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/index.cjs.js +58 -31
- package/index.esm.js +59 -32
- package/mailgun/package.json +9 -9
- package/mcp/index.cjs.js +1928 -225
- package/mcp/index.esm.js +1913 -226
- package/mcp/package.json +11 -11
- package/mcp/src/lib/mcp.config.d.ts +11 -0
- package/mcp/src/lib/service/index.d.ts +3 -0
- package/mcp/src/lib/service/mcp.manifest.d.ts +29 -0
- package/mcp/src/lib/service/mcp.route-manifest.d.ts +120 -0
- package/mcp/src/lib/service/mcp.server.factory.d.ts +14 -0
- package/mcp/src/lib/service/mcp.tool-generator.d.ts +28 -1
- package/mcp/src/lib/service/mcp.visibility.d.ts +17 -0
- package/mcp/src/lib/service/tools/mcp.tool.enum-info.d.ts +70 -0
- package/mcp/src/lib/service/tools/mcp.tool.model-info.d.ts +51 -2
- package/mcp/src/lib/service/tools/mcp.tool.url-models.d.ts +101 -0
- package/model/index.cjs.js +216 -222
- package/model/index.esm.js +217 -223
- package/model/package.json +9 -9
- package/oidc/index.cjs.js +8 -8
- package/oidc/index.esm.js +8 -8
- package/oidc/package.json +10 -10
- package/package.json +10 -10
- package/src/lib/nest/controller/model/model.api.get.service.d.ts +5 -0
- package/test/index.cjs.js +3 -3
- package/test/index.esm.js +3 -3
- package/test/package.json +11 -11
- package/twilio/package.json +8 -8
- package/zoho/index.cjs.js +3 -3
- package/zoho/index.esm.js +3 -3
- package/zoho/package.json +9 -9
package/mcp/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/mcp",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.17.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/firebase": "13.
|
|
8
|
-
"@dereekb/firebase-server": "13.
|
|
9
|
-
"@dereekb/firebase-server/oidc": "13.
|
|
10
|
-
"@dereekb/model": "13.
|
|
11
|
-
"@dereekb/nestjs": "13.
|
|
12
|
-
"@dereekb/rxjs": "13.
|
|
13
|
-
"@dereekb/util": "13.
|
|
14
|
-
"@dereekb/zoho": "13.
|
|
5
|
+
"@dereekb/analytics": "13.17.0",
|
|
6
|
+
"@dereekb/date": "13.17.0",
|
|
7
|
+
"@dereekb/firebase": "13.17.0",
|
|
8
|
+
"@dereekb/firebase-server": "13.17.0",
|
|
9
|
+
"@dereekb/firebase-server/oidc": "13.17.0",
|
|
10
|
+
"@dereekb/model": "13.17.0",
|
|
11
|
+
"@dereekb/nestjs": "13.17.0",
|
|
12
|
+
"@dereekb/rxjs": "13.17.0",
|
|
13
|
+
"@dereekb/util": "13.17.0",
|
|
14
|
+
"@dereekb/zoho": "13.17.0",
|
|
15
15
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
16
16
|
"@nestjs/common": "^11.1.19",
|
|
17
17
|
"@nestjs/core": "^11.1.19",
|
|
@@ -80,6 +80,17 @@ export declare abstract class McpModuleConfig {
|
|
|
80
80
|
* schemas, no output schemas) and emits a single boot warning.
|
|
81
81
|
*/
|
|
82
82
|
readonly mcpManifestPath?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Absolute path to a pre-rendered route manifest JSON file produced by
|
|
85
|
+
* `dbx-cli-generate-route-manifest`. When set, the runtime reads it once at
|
|
86
|
+
* boot and registers the built-in `url-models` tool, which decodes an app URL
|
|
87
|
+
* into the Firestore models its page renders.
|
|
88
|
+
*
|
|
89
|
+
* Optional. When unset or the file is missing, the runtime skips registering
|
|
90
|
+
* `url-models` and emits a single boot warning when the path was set but
|
|
91
|
+
* unreadable.
|
|
92
|
+
*/
|
|
93
|
+
readonly mcpRouteManifestPath?: string;
|
|
83
94
|
/**
|
|
84
95
|
* When `true`, the MCP server only advertises tools whose effective read-only classification is `true`.
|
|
85
96
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './analytics';
|
|
2
2
|
export * from './mcp.manifest';
|
|
3
|
+
export * from './mcp.route-manifest';
|
|
3
4
|
export * from './mcp.response-formatter';
|
|
4
5
|
export * from './mcp.server.factory';
|
|
5
6
|
export * from './mcp.tool-generator';
|
|
@@ -7,4 +8,6 @@ export * from './mcp.visibility';
|
|
|
7
8
|
export * from './tools/mcp.tool.model-get';
|
|
8
9
|
export * from './tools/mcp.tool.model-info';
|
|
9
10
|
export * from './tools/mcp.tool.model-decode';
|
|
11
|
+
export * from './tools/mcp.tool.enum-info';
|
|
12
|
+
export * from './tools/mcp.tool.url-models';
|
|
10
13
|
export * from './tools/mcp.tool.batch-execute';
|
|
@@ -82,6 +82,28 @@ export interface McpManifestModelEntry {
|
|
|
82
82
|
readonly sourceFile: string;
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* One enum value with its persisted literal and the leading JSDoc paragraph.
|
|
87
|
+
*
|
|
88
|
+
* Structural mirror of `@dereekb/dbx-cli`'s `CliModelEnumValue`. Lets the
|
|
89
|
+
* runtime `model-info` / `enum-info` tools decode raw persisted integer/string
|
|
90
|
+
* values (`s: 4`) back to human-readable names without dropping into source.
|
|
91
|
+
*/
|
|
92
|
+
export interface McpManifestEnumValue {
|
|
93
|
+
readonly name: string;
|
|
94
|
+
readonly value: number | string;
|
|
95
|
+
readonly description?: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* One TypeScript enum referenced by some model field's `enumRef`.
|
|
99
|
+
*
|
|
100
|
+
* Structural mirror of `@dereekb/dbx-cli`'s `CliModelEnum`.
|
|
101
|
+
*/
|
|
102
|
+
export interface McpManifestEnum {
|
|
103
|
+
readonly name: string;
|
|
104
|
+
readonly values: readonly McpManifestEnumValue[];
|
|
105
|
+
readonly description?: string;
|
|
106
|
+
}
|
|
85
107
|
/**
|
|
86
108
|
* One auth claim entry in the pre-rendered MCP manifest JSON.
|
|
87
109
|
*
|
|
@@ -138,6 +160,10 @@ export interface McpManifestAuth {
|
|
|
138
160
|
* manifests rendered before model catalog support landed), the runtime skips
|
|
139
161
|
* registering those tools instead of failing the boot.
|
|
140
162
|
*
|
|
163
|
+
* The optional `enums` map (keyed by enum name) carries the value→label tables
|
|
164
|
+
* `model-info` inlines and the `enum-info` static tool serves. Absent on legacy
|
|
165
|
+
* manifests; the runtime then skips registering `enum-info`.
|
|
166
|
+
*
|
|
141
167
|
* The optional `auth` section drives the built-in `whoami` static tool.
|
|
142
168
|
*/
|
|
143
169
|
export interface McpManifest {
|
|
@@ -147,6 +173,9 @@ export interface McpManifest {
|
|
|
147
173
|
readonly [key: string]: McpManifestToolEntry | undefined;
|
|
148
174
|
};
|
|
149
175
|
readonly models?: readonly McpManifestModelEntry[];
|
|
176
|
+
readonly enums?: {
|
|
177
|
+
readonly [name: string]: McpManifestEnum;
|
|
178
|
+
};
|
|
150
179
|
readonly auth?: McpManifestAuth;
|
|
151
180
|
}
|
|
152
181
|
/**
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime mirror of the build-time route manifest schema + a ported URL matcher.
|
|
3
|
+
*
|
|
4
|
+
* Structural mirror of `@dereekb/dbx-cli`'s `route-manifest.ts` types and the
|
|
5
|
+
* pure `url-match.ts` matcher, so the firebase-server/mcp runtime can consume
|
|
6
|
+
* the generated `route.manifest.json` without taking a runtime dependency on
|
|
7
|
+
* the build-time CLI package. Both sides bump {@link ROUTE_MANIFEST_VERSION}
|
|
8
|
+
* together when the manifest shape changes.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Version stamp embedded in `route.manifest.json`. Runtime loaders refuse
|
|
12
|
+
* manifests whose `version` does not match. Mirror in `@dereekb/dbx-cli`'s
|
|
13
|
+
* `ROUTE_MANIFEST_VERSION` — bump both together.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ROUTE_MANIFEST_VERSION: 1;
|
|
16
|
+
/**
|
|
17
|
+
* Whether a route-model entry resolves to a promoted id, a full key, or a
|
|
18
|
+
* keyless list. Mirror of `@dereekb/dbx-cli`'s `RouteModelKind`.
|
|
19
|
+
*/
|
|
20
|
+
export type RouteModelKind = 'id' | 'key' | 'list';
|
|
21
|
+
/**
|
|
22
|
+
* One model an app page renders. Structural mirror of `@dereekb/dbx-cli`'s
|
|
23
|
+
* `RouteManifestModelEntry`.
|
|
24
|
+
*/
|
|
25
|
+
export interface RouteManifestModelEntry {
|
|
26
|
+
readonly modelType: string;
|
|
27
|
+
readonly kind: RouteModelKind;
|
|
28
|
+
readonly keyTemplate?: string;
|
|
29
|
+
readonly description?: string;
|
|
30
|
+
readonly from?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* One UIRouter state, inheritance pre-flattened into `models`. Structural mirror
|
|
34
|
+
* of `@dereekb/dbx-cli`'s `RouteManifestStateEntry`.
|
|
35
|
+
*/
|
|
36
|
+
export interface RouteManifestStateEntry {
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly url?: string;
|
|
39
|
+
readonly fullUrl?: string;
|
|
40
|
+
readonly parentName?: string;
|
|
41
|
+
readonly paramKeys: readonly string[];
|
|
42
|
+
readonly urlParamKeys: readonly string[];
|
|
43
|
+
readonly component?: string;
|
|
44
|
+
readonly componentFile?: string;
|
|
45
|
+
readonly abstract?: boolean;
|
|
46
|
+
readonly redirectTo?: string;
|
|
47
|
+
readonly models: readonly RouteManifestModelEntry[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The full `route.manifest.json` shape. Structural mirror of `@dereekb/dbx-cli`'s
|
|
51
|
+
* `RouteManifest`.
|
|
52
|
+
*/
|
|
53
|
+
export interface RouteManifest {
|
|
54
|
+
readonly version: typeof ROUTE_MANIFEST_VERSION;
|
|
55
|
+
readonly generatedAt: string;
|
|
56
|
+
readonly app: {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly baseUrl?: string;
|
|
59
|
+
};
|
|
60
|
+
readonly states: readonly RouteManifestStateEntry[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A single resolved state match. `via` distinguishes a literal path match from
|
|
64
|
+
* a parameterised one; `params` carries the captured `:param` / `{param}`
|
|
65
|
+
* values (empty for literal matches).
|
|
66
|
+
*/
|
|
67
|
+
export interface RouteUrlMatch {
|
|
68
|
+
readonly kind: 'match';
|
|
69
|
+
readonly via: 'literal' | 'param';
|
|
70
|
+
readonly state: RouteManifestStateEntry;
|
|
71
|
+
readonly params: Readonly<Record<string, string>>;
|
|
72
|
+
readonly pathname: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* More than one state matched at the same tier.
|
|
76
|
+
*/
|
|
77
|
+
export interface RouteUrlAmbiguous {
|
|
78
|
+
readonly kind: 'ambiguous';
|
|
79
|
+
readonly states: readonly RouteManifestStateEntry[];
|
|
80
|
+
readonly pathname: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* No state matched; `candidates` holds the closest scored near-misses (top 5).
|
|
84
|
+
*/
|
|
85
|
+
export interface RouteUrlNone {
|
|
86
|
+
readonly kind: 'none';
|
|
87
|
+
readonly candidates: readonly RouteManifestStateEntry[];
|
|
88
|
+
readonly pathname: string;
|
|
89
|
+
}
|
|
90
|
+
export type RouteUrlMatchResult = RouteUrlMatch | RouteUrlAmbiguous | RouteUrlNone;
|
|
91
|
+
/**
|
|
92
|
+
* Input to {@link matchRouteManifestUrl}.
|
|
93
|
+
*/
|
|
94
|
+
export interface MatchRouteManifestUrlInput {
|
|
95
|
+
readonly manifest: RouteManifest;
|
|
96
|
+
readonly url: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Extracts the normalized pathname from a full URL or a bare path. Strips the
|
|
100
|
+
* scheme/host/port, query string, and hash; collapses an empty path to `/` and
|
|
101
|
+
* trims a single trailing slash.
|
|
102
|
+
*
|
|
103
|
+
* @param url - A full URL (`https://app.example.co/worker/x/timesheets/list`) or bare path.
|
|
104
|
+
* @returns The normalized pathname.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* parseUrlModelsPathname('https://app.hellosubs.co/worker/abc/timesheets/list/'); // => '/worker/abc/timesheets/list'
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function parseUrlModelsPathname(url: string): string;
|
|
112
|
+
/**
|
|
113
|
+
* Matches a URL against the manifest's states, preferring a literal match over
|
|
114
|
+
* a parameterised one. A tie at either tier collapses to `ambiguous`; otherwise
|
|
115
|
+
* the closest near-misses are scored and returned in a `none` result.
|
|
116
|
+
*
|
|
117
|
+
* @param input - The manifest and the URL (or pathname) to resolve.
|
|
118
|
+
* @returns A discriminated match / ambiguous / none result.
|
|
119
|
+
*/
|
|
120
|
+
export declare function matchRouteManifestUrl(input: MatchRouteManifestUrlInput): RouteUrlMatchResult;
|
|
@@ -32,7 +32,10 @@ export declare class McpServerFactoryService {
|
|
|
32
32
|
private _cachedStaticTools;
|
|
33
33
|
private _cachedManifest;
|
|
34
34
|
private _cachedManifestModels;
|
|
35
|
+
private _cachedManifestEnums;
|
|
35
36
|
private _cachedManifestAuth;
|
|
37
|
+
private _cachedRouteManifest;
|
|
38
|
+
private _routeManifestLoaded;
|
|
36
39
|
private _manifestLoaded;
|
|
37
40
|
private _loggedSkips;
|
|
38
41
|
private _warnedMissingRoleReader;
|
|
@@ -129,6 +132,17 @@ export declare class McpServerFactoryService {
|
|
|
129
132
|
*/
|
|
130
133
|
private _resolveManifest;
|
|
131
134
|
private _resetManifestCache;
|
|
135
|
+
/**
|
|
136
|
+
* Reads the pre-rendered route manifest JSON once, validates its version, and caches the result
|
|
137
|
+
* for the process lifetime. Drives whether the built-in `url-models` static tool is registered.
|
|
138
|
+
*
|
|
139
|
+
* Missing file or wrong version fall back to "no route manifest" with a single boot warning;
|
|
140
|
+
* the `url-models` tool is then simply not offered.
|
|
141
|
+
*
|
|
142
|
+
* @returns The cached route manifest, or `undefined` when none was loaded.
|
|
143
|
+
*/
|
|
144
|
+
private _resolveRouteManifest;
|
|
145
|
+
private _parseRouteManifestFile;
|
|
132
146
|
private _parseManifestFile;
|
|
133
147
|
private _applyParsedManifest;
|
|
134
148
|
/**
|
|
@@ -2,7 +2,7 @@ import { type Maybe } from '@dereekb/util';
|
|
|
2
2
|
import { type KnownOnCallFunctionType } from '@dereekb/firebase';
|
|
3
3
|
import { type ModelApiDetailsResult, type OnCallModelFunctionApiDetails, type FirebaseServerAuthData, type McpToolDetailsBuilder } from '@dereekb/firebase-server';
|
|
4
4
|
import { type Request } from 'express';
|
|
5
|
-
import { type CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { type CallToolResult, type ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
6
6
|
import { type McpManifestToolEntry } from './mcp.manifest';
|
|
7
7
|
import { type McpToolFilterMetadata } from './mcp.visibility';
|
|
8
8
|
/**
|
|
@@ -17,6 +17,12 @@ export interface McpToolListEntry {
|
|
|
17
17
|
readonly description: string;
|
|
18
18
|
readonly inputSchema: object;
|
|
19
19
|
readonly outputSchema?: object;
|
|
20
|
+
/**
|
|
21
|
+
* Standard MCP read/write hints (`readOnlyHint`, `destructiveHint`) advertised to clients so a
|
|
22
|
+
* tool's mutating behaviour is machine-readable. Resolved at boot from the effective read-only
|
|
23
|
+
* classification; see {@link resolveMcpToolAnnotations}.
|
|
24
|
+
*/
|
|
25
|
+
readonly annotations?: ToolAnnotations;
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
22
28
|
* A single MCP tool definition generated from one (modelType, callType, specifier) triple.
|
|
@@ -54,6 +60,12 @@ export interface McpToolDefinition {
|
|
|
54
60
|
* response only includes this when the pinned MCP SDK type allows it.
|
|
55
61
|
*/
|
|
56
62
|
readonly outputSchema?: object;
|
|
63
|
+
/**
|
|
64
|
+
* Standard MCP read/write hints for this tool, mirrored onto {@link staticWireEntry} and the
|
|
65
|
+
* dynamic wire path so opt-in `toolDetails` handlers keep their annotations. Resolved at boot
|
|
66
|
+
* from the effective read-only classification; see {@link resolveMcpToolAnnotations}.
|
|
67
|
+
*/
|
|
68
|
+
readonly annotations?: ToolAnnotations;
|
|
57
69
|
/**
|
|
58
70
|
* The original handler-level API details. Carries response formatters, analytics
|
|
59
71
|
* config, etc. — the controller resolves Tier 1/2/3 response shape from this.
|
|
@@ -224,6 +236,7 @@ interface BuildStaticWireEntryInput {
|
|
|
224
236
|
readonly description: string;
|
|
225
237
|
readonly inputSchema?: object;
|
|
226
238
|
readonly outputSchema?: object;
|
|
239
|
+
readonly annotations?: ToolAnnotations;
|
|
227
240
|
}
|
|
228
241
|
/**
|
|
229
242
|
* Builds the frozen wire-shape entry used by the per-request `tools/list` hot path.
|
|
@@ -235,6 +248,20 @@ interface BuildStaticWireEntryInput {
|
|
|
235
248
|
* @returns A frozen wire entry safe to share across requests.
|
|
236
249
|
*/
|
|
237
250
|
export declare function buildStaticWireEntry(input: BuildStaticWireEntryInput): McpToolListEntry;
|
|
251
|
+
/**
|
|
252
|
+
* Description prefix prepended to a mutating tool's description so MCP clients that don't render
|
|
253
|
+
* {@link ToolAnnotations} still surface the write signal in plain text.
|
|
254
|
+
*/
|
|
255
|
+
export declare const MCP_WRITE_TOOL_DESCRIPTION_PREFIX = "[WRITE] ";
|
|
256
|
+
/**
|
|
257
|
+
* Prepends {@link MCP_WRITE_TOOL_DESCRIPTION_PREFIX} to a description when its annotations mark the
|
|
258
|
+
* tool as a write (`readOnlyHint === false`). Read-only tools are returned unchanged.
|
|
259
|
+
*
|
|
260
|
+
* @param description - The base tool description.
|
|
261
|
+
* @param annotations - The resolved MCP annotations for the tool.
|
|
262
|
+
* @returns The description, prefixed with the write marker when the tool mutates.
|
|
263
|
+
*/
|
|
264
|
+
export declare function applyWriteMarker(description: string, annotations: ToolAnnotations): string;
|
|
238
265
|
/**
|
|
239
266
|
* The default specifier key used when a handler is not behind a specifier router.
|
|
240
267
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
2
|
import { type CallModelOidcScope } from '@dereekb/firebase';
|
|
3
3
|
import { type McpToolVisibility, type McpVisibilityContext, type McpVisibilityRule } from '@dereekb/firebase-server';
|
|
4
|
+
import { type ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Normalized classification of a {@link McpToolVisibility} value computed at boot.
|
|
6
7
|
*
|
|
@@ -87,6 +88,22 @@ export declare function classifyVisibility(visibility?: McpToolVisibility): Clas
|
|
|
87
88
|
* @returns The effective read-only flag, or `undefined` when neither source resolves a value.
|
|
88
89
|
*/
|
|
89
90
|
export declare function resolveEffectiveReadOnly(explicitReadOnly: Maybe<boolean>, callType: string): boolean | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Maps an effective read-only classification to the standard MCP {@link ToolAnnotations} hints
|
|
93
|
+
* advertised on `tools/list`.
|
|
94
|
+
*
|
|
95
|
+
* A definitively read-only tool advertises `{ readOnlyHint: true }`. Everything else — a known
|
|
96
|
+
* write (`false`) or an unclassified verb (`undefined`, e.g. `invoke`/custom) — fails safe to
|
|
97
|
+
* `{ readOnlyHint: false, destructiveHint: true }` so a client never mistakes an ambiguous tool
|
|
98
|
+
* for a safe read. `idempotentHint` / `openWorldHint` are intentionally left unset.
|
|
99
|
+
*
|
|
100
|
+
* Co-located with {@link resolveEffectiveReadOnly} / {@link READ_ONLY_BY_CALL_TYPE} so the
|
|
101
|
+
* read/write classification rules stay in one file.
|
|
102
|
+
*
|
|
103
|
+
* @param effectiveReadOnly - The resolved read-only classification from {@link resolveEffectiveReadOnly}.
|
|
104
|
+
* @returns The MCP annotations describing the tool's read/write behaviour.
|
|
105
|
+
*/
|
|
106
|
+
export declare function resolveMcpToolAnnotations(effectiveReadOnly: boolean | undefined): ToolAnnotations;
|
|
90
107
|
/**
|
|
91
108
|
* Resolves the OIDC scope required to invoke a given call type, or `undefined` for
|
|
92
109
|
* non-CRUD calls. Thin re-export so the tool generator doesn't need to reach into
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type McpManifestEnum } from '../mcp.manifest';
|
|
2
|
+
import { type McpToolDefinition } from '../mcp.tool-generator';
|
|
3
|
+
/**
|
|
4
|
+
* Reserved tool name for the built-in `enum-info` static tool.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ENUM_INFO_TOOL_NAME = "enum-info";
|
|
7
|
+
/**
|
|
8
|
+
* Synthetic call type used in the tool's dispatch identity. Mirrors the `info` call shared with
|
|
9
|
+
* `model-info`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ENUM_INFO_DISPATCH_CALL = "info";
|
|
12
|
+
/**
|
|
13
|
+
* Synthetic model type used in the tool's dispatch identity. Apps avoiding collisions should not
|
|
14
|
+
* register a real model literally named "enum".
|
|
15
|
+
*/
|
|
16
|
+
export declare const ENUM_INFO_DISPATCH_MODEL_TYPE = "enum";
|
|
17
|
+
/**
|
|
18
|
+
* Constructor dependencies for {@link createEnumInfoTool}.
|
|
19
|
+
*/
|
|
20
|
+
export interface CreateEnumInfoToolDeps {
|
|
21
|
+
/**
|
|
22
|
+
* Frozen enum value tables keyed by enum name, sourced from the build-time manifest's `enums`
|
|
23
|
+
* block.
|
|
24
|
+
*/
|
|
25
|
+
readonly enums: {
|
|
26
|
+
readonly [name: string]: McpManifestEnum;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Shape of the `enum-info` tool input.
|
|
31
|
+
*/
|
|
32
|
+
export interface EnumInfoToolInput {
|
|
33
|
+
/**
|
|
34
|
+
* One enum name (string) or several (string array), each matched exactly by declaration name.
|
|
35
|
+
*/
|
|
36
|
+
readonly enum: string | ReadonlyArray<string>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Output payload for the `enum-info` tool: the resolved value tables, with any unmatched names in
|
|
40
|
+
* `notFound`.
|
|
41
|
+
*/
|
|
42
|
+
export interface EnumInfoToolOutput {
|
|
43
|
+
readonly enums: ReadonlyArray<McpManifestEnum>;
|
|
44
|
+
readonly notFound?: ReadonlyArray<string>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Builds the built-in `enum-info` MCP tool definition — the symmetric counterpart to `model-info`
|
|
48
|
+
* for raw enum decoding.
|
|
49
|
+
*
|
|
50
|
+
* Resolves each requested enum name against the manifest's `enums` block and returns the matching
|
|
51
|
+
* value→label tables; misses land in `notFound`. A bare string is treated as a one-element array.
|
|
52
|
+
*
|
|
53
|
+
* Output is delivered as both stringified JSON in `content[0].text` and `structuredContent` so MCP
|
|
54
|
+
* clients can consume either form.
|
|
55
|
+
*
|
|
56
|
+
* @param deps - The frozen enum value tables loaded at boot from the MCP manifest JSON.
|
|
57
|
+
* @returns A statically-registered {@link McpToolDefinition} ready to be appended to the MCP server
|
|
58
|
+
* factory's tool registry.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createEnumInfoTool(deps: CreateEnumInfoToolDeps): McpToolDefinition;
|
|
61
|
+
/**
|
|
62
|
+
* Resolves each requested enum name against the registered value tables.
|
|
63
|
+
*
|
|
64
|
+
* @param names - The requested enum declaration names.
|
|
65
|
+
* @param enums - The registered enum value tables keyed by name.
|
|
66
|
+
* @returns The matched tables, with any unmatched names in `notFound`.
|
|
67
|
+
*
|
|
68
|
+
* @__NO_SIDE_EFFECTS__
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveEnumInfoOutput(names: readonly string[], enums: CreateEnumInfoToolDeps['enums']): EnumInfoToolOutput;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type McpManifestModelEntry } from '../mcp.manifest';
|
|
1
|
+
import { type McpManifestEnum, type McpManifestModelEntry } from '../mcp.manifest';
|
|
2
2
|
import { type McpToolDefinition } from '../mcp.tool-generator';
|
|
3
3
|
/**
|
|
4
4
|
* Reserved tool name for the built-in `model-info` static tool.
|
|
@@ -32,6 +32,15 @@ export interface CreateModelInfoToolDeps {
|
|
|
32
32
|
* manifest JSON.
|
|
33
33
|
*/
|
|
34
34
|
readonly manifest: readonly McpManifestModelEntry[];
|
|
35
|
+
/**
|
|
36
|
+
* Optional enum value tables, keyed by enum name, sourced from the build-time manifest's `enums`
|
|
37
|
+
* block. When present, the value→label table for every enum referenced (by `enumRef`) on a
|
|
38
|
+
* returned model's fields is attached as a top-level `enums` section — but only when full field
|
|
39
|
+
* detail is returned, so the default compact modes stay small.
|
|
40
|
+
*/
|
|
41
|
+
readonly enums?: {
|
|
42
|
+
readonly [name: string]: McpManifestEnum;
|
|
43
|
+
};
|
|
35
44
|
}
|
|
36
45
|
/**
|
|
37
46
|
* Public shape of the `model-info` tool input. Every field is optional; the combination selects
|
|
@@ -112,8 +121,12 @@ export interface ModelInfoNotFound {
|
|
|
112
121
|
* - `list`: a summary (or, with `fields: true`, full) list — used by `modelGroup` and `all`.
|
|
113
122
|
* - `single`: full detail for one `model` string.
|
|
114
123
|
* - `multiple`: full detail per match for a `model` array, with misses in `notFound`.
|
|
124
|
+
*
|
|
125
|
+
* The orthogonal `enums` section is attached only when full field detail is returned and the
|
|
126
|
+
* returned models reference at least one enum present in the manifest — the default compact modes
|
|
127
|
+
* (`groups`, summary `list`) never carry it.
|
|
115
128
|
*/
|
|
116
|
-
export type ModelInfoToolOutput = {
|
|
129
|
+
export type ModelInfoToolOutput = ({
|
|
117
130
|
readonly mode: 'groups';
|
|
118
131
|
readonly groups: ReadonlyArray<ModelInfoGroupCount>;
|
|
119
132
|
readonly totalModels: number;
|
|
@@ -129,6 +142,8 @@ export type ModelInfoToolOutput = {
|
|
|
129
142
|
readonly mode: 'multiple';
|
|
130
143
|
readonly models: ReadonlyArray<ModelInfoModelRow>;
|
|
131
144
|
readonly notFound?: ReadonlyArray<ModelInfoNotFound>;
|
|
145
|
+
}) & {
|
|
146
|
+
readonly enums?: ReadonlyArray<McpManifestEnum>;
|
|
132
147
|
};
|
|
133
148
|
/**
|
|
134
149
|
* Builds the built-in `model-info` MCP tool definition.
|
|
@@ -162,3 +177,37 @@ export declare function createModelInfoTool(deps: CreateModelInfoToolDeps): McpT
|
|
|
162
177
|
* @__NO_SIDE_EFFECTS__
|
|
163
178
|
*/
|
|
164
179
|
export declare function findModelEntry(query: string, manifest: ReadonlyArray<McpManifestModelEntry>): McpManifestModelEntry | undefined;
|
|
180
|
+
/**
|
|
181
|
+
* JSON-schema for one enum value→label table. Shared with the `enum-info` tool so both advertise the
|
|
182
|
+
* identical enum shape.
|
|
183
|
+
*/
|
|
184
|
+
export declare const ENUM_TABLE_SCHEMA: {
|
|
185
|
+
readonly type: "object";
|
|
186
|
+
readonly required: readonly ["name", "values"];
|
|
187
|
+
readonly properties: {
|
|
188
|
+
readonly name: {
|
|
189
|
+
readonly type: "string";
|
|
190
|
+
};
|
|
191
|
+
readonly description: {
|
|
192
|
+
readonly type: "string";
|
|
193
|
+
};
|
|
194
|
+
readonly values: {
|
|
195
|
+
readonly type: "array";
|
|
196
|
+
readonly items: {
|
|
197
|
+
readonly type: "object";
|
|
198
|
+
readonly required: readonly ["name", "value"];
|
|
199
|
+
readonly properties: {
|
|
200
|
+
readonly name: {
|
|
201
|
+
readonly type: "string";
|
|
202
|
+
};
|
|
203
|
+
readonly value: {
|
|
204
|
+
readonly type: readonly ["string", "number"];
|
|
205
|
+
};
|
|
206
|
+
readonly description: {
|
|
207
|
+
readonly type: "string";
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { type FirestoreModelKey } from '@dereekb/firebase';
|
|
2
|
+
import { type ModelAccessMultiReadResult } from '@dereekb/firebase-server';
|
|
3
|
+
import { type McpToolDefinition } from '../mcp.tool-generator';
|
|
4
|
+
import { type RouteManifest, type RouteManifestModelEntry } from '../mcp.route-manifest';
|
|
5
|
+
import { type McpModelGetReadDocuments, type McpModelGetResolveIdentity } from './mcp.tool.model-get';
|
|
6
|
+
/**
|
|
7
|
+
* Reserved tool name for the built-in `url-models` static tool.
|
|
8
|
+
*/
|
|
9
|
+
export declare const URL_MODELS_TOOL_NAME = "url-models";
|
|
10
|
+
/**
|
|
11
|
+
* Synthetic call type used in the tool's dispatch identity.
|
|
12
|
+
*/
|
|
13
|
+
export declare const URL_MODELS_DISPATCH_CALL = "url-models";
|
|
14
|
+
/**
|
|
15
|
+
* Synthetic model type used in the tool's dispatch identity. The tool isn't
|
|
16
|
+
* bound to a real model (the `url` is its input), so we use the literal "route".
|
|
17
|
+
*/
|
|
18
|
+
export declare const URL_MODELS_DISPATCH_MODEL_TYPE = "route";
|
|
19
|
+
/**
|
|
20
|
+
* Why a model binding could not be resolved into a concrete key.
|
|
21
|
+
*/
|
|
22
|
+
export type UrlModelUnresolvedReason = 'missing-param' | 'subcollection-requires-key-template' | 'unknown-model-type' | 'auth-required';
|
|
23
|
+
/**
|
|
24
|
+
* One resolved model binding for a matched page.
|
|
25
|
+
*/
|
|
26
|
+
export interface ResolvedRouteModel {
|
|
27
|
+
readonly modelType: string;
|
|
28
|
+
readonly kind: RouteManifestModelEntry['kind'];
|
|
29
|
+
readonly keyTemplate?: string;
|
|
30
|
+
readonly description?: string;
|
|
31
|
+
readonly from?: string;
|
|
32
|
+
/**
|
|
33
|
+
* The concrete FirestoreModelKey, when the binding resolved (`id`/`key` kinds).
|
|
34
|
+
*/
|
|
35
|
+
readonly key?: FirestoreModelKey;
|
|
36
|
+
/**
|
|
37
|
+
* Present when the binding could not be turned into a key.
|
|
38
|
+
*/
|
|
39
|
+
readonly unresolved?: {
|
|
40
|
+
readonly reason: UrlModelUnresolvedReason;
|
|
41
|
+
readonly message: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Documents loaded for one model type (when `load` is requested).
|
|
46
|
+
*/
|
|
47
|
+
export interface UrlModelLoadedGroup {
|
|
48
|
+
readonly modelType: string;
|
|
49
|
+
readonly results: ModelAccessMultiReadResult['results'];
|
|
50
|
+
readonly errors: ModelAccessMultiReadResult['errors'];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Constructor dependencies for {@link createUrlModelsTool}.
|
|
54
|
+
*/
|
|
55
|
+
export interface CreateUrlModelsToolDeps {
|
|
56
|
+
/**
|
|
57
|
+
* The pre-rendered route manifest used to match URLs to states.
|
|
58
|
+
*/
|
|
59
|
+
readonly routeManifest: RouteManifest;
|
|
60
|
+
/**
|
|
61
|
+
* Reads a batch of model documents (shared with `model-get`).
|
|
62
|
+
*/
|
|
63
|
+
readonly readDocuments: McpModelGetReadDocuments;
|
|
64
|
+
/**
|
|
65
|
+
* Resolves a model type's registered identity so `id` key templates can be
|
|
66
|
+
* promoted to `<collectionName>/<id>` (shared with `model-get`).
|
|
67
|
+
*/
|
|
68
|
+
readonly resolveIdentity: McpModelGetResolveIdentity;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Shape of the `url-models` tool input.
|
|
72
|
+
*/
|
|
73
|
+
export interface UrlModelsToolInput {
|
|
74
|
+
readonly url: string;
|
|
75
|
+
readonly models?: ReadonlyArray<string>;
|
|
76
|
+
readonly keysOnly?: boolean;
|
|
77
|
+
readonly load?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Overrides the uid used to fill `{authUid}` placeholders when resolving model
|
|
80
|
+
* keys (defaults to the authenticated caller). Use to preview the models
|
|
81
|
+
* another user would see on a page. Does not affect the document-load path —
|
|
82
|
+
* `load` still reads via the calling user's permissions.
|
|
83
|
+
*/
|
|
84
|
+
readonly currentUserUid?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Builds the built-in `url-models` MCP tool definition.
|
|
88
|
+
*
|
|
89
|
+
* Matches a pasted app URL against the build-time route manifest and returns the
|
|
90
|
+
* Firestore models the page renders — model types plus concrete keys with the
|
|
91
|
+
* route params and `{authUid}` substituted. Optionally filtered to specific
|
|
92
|
+
* `models`, reduced to keys-only, or loaded via the same permission-checked read
|
|
93
|
+
* path as `model-get`.
|
|
94
|
+
*
|
|
95
|
+
* A URL that matches no state returns a structured `{ matched: null, candidates }`
|
|
96
|
+
* (not an error) so the caller can suggest near-misses.
|
|
97
|
+
*
|
|
98
|
+
* @param deps - The route manifest plus the shared read-documents / identity callbacks.
|
|
99
|
+
* @returns A statically-registered {@link McpToolDefinition}.
|
|
100
|
+
*/
|
|
101
|
+
export declare function createUrlModelsTool(deps: CreateUrlModelsToolDeps): McpToolDefinition;
|