@praxis-ai/mcp-plus 1.0.0 → 1.0.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 +26 -0
- package/dist/index.d.mts +72 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +346 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,11 +83,37 @@ const surface = lowerExposurePlanToMcpSurface(plan);
|
|
|
83
83
|
|
|
84
84
|
`surface.tools` is still MCP-compatible. `surface.sidecar` contains compact server, tool, and skill index metadata for MCP+-aware wrappers or host adapters.
|
|
85
85
|
|
|
86
|
+
## Validate A Learned Profile Proposal
|
|
87
|
+
|
|
88
|
+
`mcp_plus.init` and `mcp_plus.reprofile` are virtual MCP-shaped control tools. The model submits a structured proposal as tool arguments; MCP+ validates and normalizes the proposal; the host decides whether to accept, merge, and persist it.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { createInitToolDeclaration, createLearnedProfileFromProposal, mergeMcpPlusPolicy, validateProfileProposal } from '@praxis-ai/mcp-plus';
|
|
92
|
+
|
|
93
|
+
const initTool = createInitToolDeclaration();
|
|
94
|
+
const validation = validateProfileProposal(modelProposal, nativeToolsFromMcpToolsList, {
|
|
95
|
+
serverId: manifest.server.id,
|
|
96
|
+
alwaysIndexTools: manifest.exposure?.alwaysIndexTools
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (validation.valid) {
|
|
100
|
+
const learnedProfile = createLearnedProfileFromProposal(modelProposal);
|
|
101
|
+
const effectiveManifest = mergeMcpPlusPolicy({
|
|
102
|
+
manifest,
|
|
103
|
+
learnedProfile,
|
|
104
|
+
runtimeOverlay
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Learned profiles use `schemaVersion: "mcp-plus.profile.v1"`. Runtime exposure mode such as `expanded`, `indexed`, or `frozen` belongs to host-owned runtime overlay, not to the model proposal.
|
|
110
|
+
|
|
86
111
|
## Core Ideas
|
|
87
112
|
|
|
88
113
|
- pinned tools keep full native MCP schemas visible;
|
|
89
114
|
- indexed tools fold into compact capability cards;
|
|
90
115
|
- `mcp_plus.expand` can activate folded tools in wrapper mode;
|
|
116
|
+
- `mcp_plus.init` and `mcp_plus.reprofile` define profile proposal contracts without owning runtime storage;
|
|
91
117
|
- skill indexes stay compact while full skill notes live in a server-bound skill store;
|
|
92
118
|
- `mcp_plus.finish` lets a wrapper ask the model to preserve reusable workflow experience.
|
|
93
119
|
|
package/dist/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ type JsonSchema = {
|
|
|
3
3
|
type?: string;
|
|
4
4
|
properties?: Record<string, JsonSchema>;
|
|
5
5
|
required?: string[];
|
|
6
|
-
additionalProperties?: boolean;
|
|
6
|
+
additionalProperties?: boolean | JsonSchema;
|
|
7
7
|
description?: string;
|
|
8
8
|
enum?: string[];
|
|
9
9
|
items?: JsonSchema;
|
|
@@ -127,6 +127,76 @@ type ExpandResult = {
|
|
|
127
127
|
activatedTools: string[];
|
|
128
128
|
mode: ExposureMode;
|
|
129
129
|
};
|
|
130
|
+
declare const MCP_PLUS_PROFILE_SCHEMA_VERSION: "mcp-plus.profile.v1";
|
|
131
|
+
type McpPlusProfileSchemaVersion = typeof MCP_PLUS_PROFILE_SCHEMA_VERSION;
|
|
132
|
+
type McpPlusProfileToolCard = {
|
|
133
|
+
title?: string;
|
|
134
|
+
summary: string;
|
|
135
|
+
keywords?: string[];
|
|
136
|
+
};
|
|
137
|
+
type McpPlusProfileProposal = {
|
|
138
|
+
serverId: string;
|
|
139
|
+
pinnedTools: string[];
|
|
140
|
+
warmTools?: string[];
|
|
141
|
+
indexedTools: string[];
|
|
142
|
+
alwaysIndexTools?: string[];
|
|
143
|
+
toolCards: Record<string, McpPlusProfileToolCard>;
|
|
144
|
+
skillChapters?: McpPlusSkillChapter[];
|
|
145
|
+
rationale?: Record<string, string>;
|
|
146
|
+
modeHint?: never;
|
|
147
|
+
};
|
|
148
|
+
type McpPlusLearnedProfile = {
|
|
149
|
+
schemaVersion: McpPlusProfileSchemaVersion;
|
|
150
|
+
serverId: string;
|
|
151
|
+
pinnedTools?: string[];
|
|
152
|
+
warmTools?: string[];
|
|
153
|
+
indexedTools?: string[];
|
|
154
|
+
alwaysIndexTools?: string[];
|
|
155
|
+
toolCards?: Record<string, McpPlusProfileToolCard>;
|
|
156
|
+
skillChapters?: McpPlusSkillChapter[];
|
|
157
|
+
rationale?: Record<string, string>;
|
|
158
|
+
};
|
|
159
|
+
type McpPlusRuntimeOverlay = {
|
|
160
|
+
serverId: string;
|
|
161
|
+
sessionId?: string;
|
|
162
|
+
exposure?: McpPlusExposurePolicy;
|
|
163
|
+
skills?: McpPlusSkillPolicy;
|
|
164
|
+
state?: {
|
|
165
|
+
mode?: ExposureMode;
|
|
166
|
+
activeTools?: string[];
|
|
167
|
+
pendingReprofile?: boolean;
|
|
168
|
+
counters?: Record<string, number>;
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
type ProfileProposalValidationIssueCode = 'invalid_shape' | 'server_mismatch' | 'unknown_tool' | 'always_index_pinned' | 'invalid_tool_card' | 'invalid_skill_chapter' | 'reserved_runtime_field';
|
|
172
|
+
type ProfileProposalValidationIssue = {
|
|
173
|
+
code: ProfileProposalValidationIssueCode;
|
|
174
|
+
message: string;
|
|
175
|
+
path: string;
|
|
176
|
+
toolName?: string;
|
|
177
|
+
};
|
|
178
|
+
type ProfileProposalValidationOptions = {
|
|
179
|
+
serverId?: string;
|
|
180
|
+
alwaysIndexTools?: readonly string[];
|
|
181
|
+
};
|
|
182
|
+
type ProfileProposalValidationResult = {
|
|
183
|
+
valid: boolean;
|
|
184
|
+
issues: ProfileProposalValidationIssue[];
|
|
185
|
+
};
|
|
186
|
+
type MergeMcpPlusPolicyInput = {
|
|
187
|
+
manifest: McpPlusManifest;
|
|
188
|
+
learnedProfile?: McpPlusLearnedProfile;
|
|
189
|
+
runtimeOverlay?: McpPlusRuntimeOverlay;
|
|
190
|
+
};
|
|
191
|
+
declare function createInitToolDeclaration(): NativeToolDeclaration;
|
|
192
|
+
declare function createReprofileToolDeclaration(): NativeToolDeclaration;
|
|
193
|
+
declare function validateProfileProposal(proposal: unknown, nativeTools: readonly NativeToolDeclaration[], options?: ProfileProposalValidationOptions): ProfileProposalValidationResult;
|
|
194
|
+
declare function normalizeProfileProposal(proposal: McpPlusProfileProposal): McpPlusProfileProposal;
|
|
195
|
+
declare function createLearnedProfileFromProposal(proposal: McpPlusProfileProposal): McpPlusLearnedProfile;
|
|
196
|
+
declare function mergeManifestWithProfileProposal(manifest: McpPlusManifest, proposal: McpPlusProfileProposal, options?: {
|
|
197
|
+
runtimeOverlay?: McpPlusRuntimeOverlay;
|
|
198
|
+
}): McpPlusManifest;
|
|
199
|
+
declare function mergeMcpPlusPolicy(input: MergeMcpPlusPolicyInput): McpPlusManifest;
|
|
130
200
|
declare function compileMcpPlusManifest(manifest: McpPlusManifest, nativeTools: NativeToolDeclaration[]): ExposureGraph;
|
|
131
201
|
declare function planExposure(graph: ExposureGraph, state: ExposureState): ExposurePlan;
|
|
132
202
|
declare function createExpandToolDeclaration(): NativeToolDeclaration;
|
|
@@ -145,5 +215,5 @@ declare class McpPlusWrapperRuntime {
|
|
|
145
215
|
expand(request: ExpandRequest): ExpandResult;
|
|
146
216
|
}
|
|
147
217
|
//#endregion
|
|
148
|
-
export { CapabilityActivation, ExpandRequest, ExpandResult, ExposureGraph, ExposureImpactEstimate, ExposureMode, ExposurePlan, ExposurePlanner, ExposureState, JsonSchema, McpCompatibleSurface, McpPlusExposurePolicy, McpPlusManifest, McpPlusServerManifest, McpPlusSidecar, McpPlusSkillChapter, McpPlusSkillPolicy, McpPlusWrapperRuntime, NativeToolDeclaration, ServerCard, SkillIndexEntry, ToolCardPolicy, ToolIndexEntry, compileMcpPlusManifest, createExpandToolDeclaration, defineMcpPlusManifest, estimateExposurePlanImpact, lowerExposurePlanToMcpSurface, planExposure };
|
|
218
|
+
export { CapabilityActivation, ExpandRequest, ExpandResult, ExposureGraph, ExposureImpactEstimate, ExposureMode, ExposurePlan, ExposurePlanner, ExposureState, JsonSchema, MCP_PLUS_PROFILE_SCHEMA_VERSION, McpCompatibleSurface, McpPlusExposurePolicy, McpPlusLearnedProfile, McpPlusManifest, McpPlusProfileProposal, McpPlusProfileSchemaVersion, McpPlusProfileToolCard, McpPlusRuntimeOverlay, McpPlusServerManifest, McpPlusSidecar, McpPlusSkillChapter, McpPlusSkillPolicy, McpPlusWrapperRuntime, MergeMcpPlusPolicyInput, NativeToolDeclaration, ProfileProposalValidationIssue, ProfileProposalValidationIssueCode, ProfileProposalValidationOptions, ProfileProposalValidationResult, ServerCard, SkillIndexEntry, ToolCardPolicy, ToolIndexEntry, compileMcpPlusManifest, createExpandToolDeclaration, createInitToolDeclaration, createLearnedProfileFromProposal, createReprofileToolDeclaration, defineMcpPlusManifest, estimateExposurePlanImpact, lowerExposurePlanToMcpSurface, mergeManifestWithProfileProposal, mergeMcpPlusPolicy, normalizeProfileProposal, planExposure, validateProfileProposal };
|
|
149
219
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";KAAY,UAAA;EAAA,IAAA,CAAA,EAAA,MAAU;EAEU,UAAA,CAAA,EAAf,MAAe,CAAA,MAAA,EAAA,UAAA,CAAA;EAAf,QAAA,CAAA,EAAA,MAAA,EAAA;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -2,9 +2,159 @@
|
|
|
2
2
|
function defineMcpPlusManifest(manifest) {
|
|
3
3
|
return manifest;
|
|
4
4
|
}
|
|
5
|
+
const MCP_PLUS_PROFILE_SCHEMA_VERSION = "mcp-plus.profile.v1";
|
|
5
6
|
const DEFAULT_FREEZE_AFTER_UNUSED_TURNS = 5;
|
|
6
7
|
const DEFAULT_WARM_AFTER_CONSECUTIVE_CALLS = 2;
|
|
7
8
|
const DEFAULT_DEMOTE_AFTER_UNUSED_TURNS = 2;
|
|
9
|
+
function createInitToolDeclaration() {
|
|
10
|
+
return {
|
|
11
|
+
name: "mcp_plus.init",
|
|
12
|
+
description: [
|
|
13
|
+
"Submit an initial MCP+ exposure profile proposal for this standard MCP server.",
|
|
14
|
+
"Use only tool names from the current tools/list result.",
|
|
15
|
+
"Do not include runtime exposure mode; expanded/indexed/frozen is host-owned session state."
|
|
16
|
+
].join(" "),
|
|
17
|
+
inputSchema: createProfileProposalInputSchema("Initial profile proposal to validate.")
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function createReprofileToolDeclaration() {
|
|
21
|
+
return {
|
|
22
|
+
name: "mcp_plus.reprofile",
|
|
23
|
+
description: [
|
|
24
|
+
"Submit an updated MCP+ exposure profile proposal after host-selected reprofile.",
|
|
25
|
+
"Use only tool names from the current tools/list result.",
|
|
26
|
+
"This is a proposal only; the host decides whether to accept, merge, and persist it."
|
|
27
|
+
].join(" "),
|
|
28
|
+
inputSchema: createProfileProposalInputSchema("Updated profile proposal to validate.")
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function validateProfileProposal(proposal, nativeTools, options = {}) {
|
|
32
|
+
const issues = [];
|
|
33
|
+
const knownToolNames = new Set(nativeTools.map((tool) => tool.name));
|
|
34
|
+
if (!isRecord(proposal)) return {
|
|
35
|
+
valid: false,
|
|
36
|
+
issues: [{
|
|
37
|
+
code: "invalid_shape",
|
|
38
|
+
message: "Profile proposal must be an object.",
|
|
39
|
+
path: "$"
|
|
40
|
+
}]
|
|
41
|
+
};
|
|
42
|
+
if ("modeHint" in proposal) issues.push({
|
|
43
|
+
code: "reserved_runtime_field",
|
|
44
|
+
message: "modeHint is runtime overlay state and is not allowed in McpPlusProfileProposal v1.",
|
|
45
|
+
path: "$.modeHint"
|
|
46
|
+
});
|
|
47
|
+
if (!isString(proposal.serverId)) issues.push({
|
|
48
|
+
code: "invalid_shape",
|
|
49
|
+
message: "serverId must be a string.",
|
|
50
|
+
path: "$.serverId"
|
|
51
|
+
});
|
|
52
|
+
else if (options.serverId !== void 0 && proposal.serverId !== options.serverId) issues.push({
|
|
53
|
+
code: "server_mismatch",
|
|
54
|
+
message: `Profile proposal serverId ${proposal.serverId} does not match expected server ${options.serverId}.`,
|
|
55
|
+
path: "$.serverId"
|
|
56
|
+
});
|
|
57
|
+
const pinnedTools = readStringArray(proposal, "pinnedTools", issues, true);
|
|
58
|
+
const warmTools = readStringArray(proposal, "warmTools", issues, false);
|
|
59
|
+
const indexedTools = readStringArray(proposal, "indexedTools", issues, true);
|
|
60
|
+
const alwaysIndexTools = readStringArray(proposal, "alwaysIndexTools", issues, false);
|
|
61
|
+
const protectedAlwaysIndexTools = new Set([...options.alwaysIndexTools ?? [], ...alwaysIndexTools]);
|
|
62
|
+
validateToolNames(pinnedTools, knownToolNames, issues, "$.pinnedTools");
|
|
63
|
+
validateToolNames(warmTools, knownToolNames, issues, "$.warmTools");
|
|
64
|
+
validateToolNames(indexedTools, knownToolNames, issues, "$.indexedTools");
|
|
65
|
+
validateToolNames(alwaysIndexTools, knownToolNames, issues, "$.alwaysIndexTools");
|
|
66
|
+
for (const toolName of pinnedTools) if (protectedAlwaysIndexTools.has(toolName)) issues.push({
|
|
67
|
+
code: "always_index_pinned",
|
|
68
|
+
message: `Tool ${toolName} is always-index and cannot be pinned by a profile proposal.`,
|
|
69
|
+
path: "$.pinnedTools",
|
|
70
|
+
toolName
|
|
71
|
+
});
|
|
72
|
+
validateToolCards(proposal.toolCards, knownToolNames, issues);
|
|
73
|
+
validateSkillChapters(proposal.skillChapters, issues);
|
|
74
|
+
return {
|
|
75
|
+
valid: issues.length === 0,
|
|
76
|
+
issues
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function normalizeProfileProposal(proposal) {
|
|
80
|
+
return {
|
|
81
|
+
serverId: proposal.serverId,
|
|
82
|
+
pinnedTools: uniqueSorted(proposal.pinnedTools),
|
|
83
|
+
warmTools: optionalUniqueSorted(proposal.warmTools),
|
|
84
|
+
indexedTools: uniqueSorted(proposal.indexedTools),
|
|
85
|
+
alwaysIndexTools: optionalUniqueSorted(proposal.alwaysIndexTools),
|
|
86
|
+
toolCards: cloneToolCards(proposal.toolCards),
|
|
87
|
+
skillChapters: proposal.skillChapters?.map((chapter) => ({ ...chapter })),
|
|
88
|
+
rationale: proposal.rationale === void 0 ? void 0 : { ...proposal.rationale }
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function createLearnedProfileFromProposal(proposal) {
|
|
92
|
+
const normalized = normalizeProfileProposal(proposal);
|
|
93
|
+
return {
|
|
94
|
+
schemaVersion: MCP_PLUS_PROFILE_SCHEMA_VERSION,
|
|
95
|
+
serverId: normalized.serverId,
|
|
96
|
+
pinnedTools: normalized.pinnedTools,
|
|
97
|
+
warmTools: normalized.warmTools,
|
|
98
|
+
indexedTools: normalized.indexedTools,
|
|
99
|
+
alwaysIndexTools: normalized.alwaysIndexTools,
|
|
100
|
+
toolCards: normalized.toolCards,
|
|
101
|
+
skillChapters: normalized.skillChapters,
|
|
102
|
+
rationale: normalized.rationale
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function mergeManifestWithProfileProposal(manifest, proposal, options = {}) {
|
|
106
|
+
return mergeMcpPlusPolicy({
|
|
107
|
+
manifest,
|
|
108
|
+
learnedProfile: createLearnedProfileFromProposal(proposal),
|
|
109
|
+
runtimeOverlay: options.runtimeOverlay
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function mergeMcpPlusPolicy(input) {
|
|
113
|
+
const manifest = input.manifest;
|
|
114
|
+
const learnedProfile = input.learnedProfile;
|
|
115
|
+
const runtimeOverlay = input.runtimeOverlay;
|
|
116
|
+
const manifestExposure = manifest.exposure ?? {};
|
|
117
|
+
const overlayExposure = runtimeOverlay?.exposure ?? {};
|
|
118
|
+
assertProfileServerMatchesManifest(manifest, learnedProfile, "learnedProfile");
|
|
119
|
+
assertOverlayServerMatchesManifest(manifest, runtimeOverlay);
|
|
120
|
+
const alwaysIndexTools = uniqueSorted([
|
|
121
|
+
...manifestExposure.alwaysIndexTools ?? [],
|
|
122
|
+
...learnedProfile?.alwaysIndexTools ?? [],
|
|
123
|
+
...overlayExposure.alwaysIndexTools ?? []
|
|
124
|
+
]);
|
|
125
|
+
const alwaysIndexToolSet = new Set(alwaysIndexTools);
|
|
126
|
+
const pinnedTools = uniqueSorted([
|
|
127
|
+
...manifestExposure.pinnedTools ?? [],
|
|
128
|
+
...(learnedProfile?.pinnedTools ?? []).filter((toolName) => !alwaysIndexToolSet.has(toolName)),
|
|
129
|
+
...(overlayExposure.pinnedTools ?? []).filter((toolName) => !alwaysIndexToolSet.has(toolName))
|
|
130
|
+
]);
|
|
131
|
+
const warmTools = uniqueSorted([
|
|
132
|
+
...manifestExposure.warmTools ?? [],
|
|
133
|
+
...(learnedProfile?.warmTools ?? []).filter((toolName) => !alwaysIndexToolSet.has(toolName)),
|
|
134
|
+
...(overlayExposure.warmTools ?? []).filter((toolName) => !alwaysIndexToolSet.has(toolName))
|
|
135
|
+
]);
|
|
136
|
+
const indexedTools = uniqueSorted([
|
|
137
|
+
...manifestExposure.indexedTools ?? [],
|
|
138
|
+
...learnedProfile?.indexedTools ?? [],
|
|
139
|
+
...overlayExposure.indexedTools ?? [],
|
|
140
|
+
...alwaysIndexTools
|
|
141
|
+
]);
|
|
142
|
+
const toolCards = Object.assign({}, learnedProfile?.toolCards, manifestExposure.toolCards, overlayExposure.toolCards);
|
|
143
|
+
const skillChapters = mergeSkillChapters(learnedProfile?.skillChapters, manifest.skills?.chapters, runtimeOverlay?.skills?.chapters);
|
|
144
|
+
return {
|
|
145
|
+
server: { ...manifest.server },
|
|
146
|
+
exposure: {
|
|
147
|
+
...manifestExposure,
|
|
148
|
+
...overlayExposure,
|
|
149
|
+
pinnedTools,
|
|
150
|
+
warmTools,
|
|
151
|
+
indexedTools,
|
|
152
|
+
alwaysIndexTools,
|
|
153
|
+
toolCards
|
|
154
|
+
},
|
|
155
|
+
skills: manifest.skills === void 0 && runtimeOverlay?.skills === void 0 && skillChapters.length === 0 ? void 0 : Object.assign({}, manifest.skills, runtimeOverlay?.skills, { chapters: skillChapters })
|
|
156
|
+
};
|
|
157
|
+
}
|
|
8
158
|
function compileMcpPlusManifest(manifest, nativeTools) {
|
|
9
159
|
const pinnedToolNames = new Set(manifest.exposure?.pinnedTools);
|
|
10
160
|
const warmToolNames = new Set(manifest.exposure?.warmTools);
|
|
@@ -203,7 +353,202 @@ function isMeaningfulSearchTerm(term) {
|
|
|
203
353
|
if (term === "") return false;
|
|
204
354
|
return [...term].some((character) => (character.codePointAt(0) ?? 0) > 127) || term.length >= 3;
|
|
205
355
|
}
|
|
356
|
+
function createProfileProposalInputSchema(description) {
|
|
357
|
+
return {
|
|
358
|
+
type: "object",
|
|
359
|
+
description,
|
|
360
|
+
properties: {
|
|
361
|
+
serverId: {
|
|
362
|
+
type: "string",
|
|
363
|
+
description: "MCP server id this proposal applies to."
|
|
364
|
+
},
|
|
365
|
+
pinnedTools: {
|
|
366
|
+
type: "array",
|
|
367
|
+
description: "Tool names to keep visible as full schemas when the server is expanded.",
|
|
368
|
+
items: { type: "string" }
|
|
369
|
+
},
|
|
370
|
+
warmTools: {
|
|
371
|
+
type: "array",
|
|
372
|
+
description: "Tool names that may stay visible initially, subject to host-owned demotion policy.",
|
|
373
|
+
items: { type: "string" }
|
|
374
|
+
},
|
|
375
|
+
indexedTools: {
|
|
376
|
+
type: "array",
|
|
377
|
+
description: "Tool names represented by compact capability cards until activated.",
|
|
378
|
+
items: { type: "string" }
|
|
379
|
+
},
|
|
380
|
+
alwaysIndexTools: {
|
|
381
|
+
type: "array",
|
|
382
|
+
description: "Tool names that should remain indexed and must not be automatically pinned.",
|
|
383
|
+
items: { type: "string" }
|
|
384
|
+
},
|
|
385
|
+
toolCards: {
|
|
386
|
+
type: "object",
|
|
387
|
+
description: "Compact capability cards keyed by tool name.",
|
|
388
|
+
additionalProperties: {
|
|
389
|
+
type: "object",
|
|
390
|
+
properties: {
|
|
391
|
+
title: { type: "string" },
|
|
392
|
+
summary: { type: "string" },
|
|
393
|
+
keywords: {
|
|
394
|
+
type: "array",
|
|
395
|
+
items: { type: "string" }
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
required: ["summary"],
|
|
399
|
+
additionalProperties: false
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
skillChapters: {
|
|
403
|
+
type: "array",
|
|
404
|
+
description: "Initial compact server-bound skill chapters.",
|
|
405
|
+
items: {
|
|
406
|
+
type: "object",
|
|
407
|
+
properties: {
|
|
408
|
+
id: { type: "string" },
|
|
409
|
+
title: { type: "string" },
|
|
410
|
+
summary: { type: "string" }
|
|
411
|
+
},
|
|
412
|
+
required: [
|
|
413
|
+
"id",
|
|
414
|
+
"title",
|
|
415
|
+
"summary"
|
|
416
|
+
],
|
|
417
|
+
additionalProperties: false
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
rationale: {
|
|
421
|
+
type: "object",
|
|
422
|
+
description: "Optional short rationale keyed by tool name or policy area.",
|
|
423
|
+
additionalProperties: { type: "string" }
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
required: [
|
|
427
|
+
"serverId",
|
|
428
|
+
"pinnedTools",
|
|
429
|
+
"indexedTools",
|
|
430
|
+
"toolCards"
|
|
431
|
+
],
|
|
432
|
+
additionalProperties: false
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
function isRecord(value) {
|
|
436
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
437
|
+
}
|
|
438
|
+
function isString(value) {
|
|
439
|
+
return typeof value === "string";
|
|
440
|
+
}
|
|
441
|
+
function readStringArray(object, key, issues, required) {
|
|
442
|
+
const value = object[key];
|
|
443
|
+
if (value === void 0) {
|
|
444
|
+
if (required) issues.push({
|
|
445
|
+
code: "invalid_shape",
|
|
446
|
+
message: `${key} must be an array of strings.`,
|
|
447
|
+
path: `$.${key}`
|
|
448
|
+
});
|
|
449
|
+
return [];
|
|
450
|
+
}
|
|
451
|
+
if (!Array.isArray(value) || !value.every((item) => isString(item))) {
|
|
452
|
+
issues.push({
|
|
453
|
+
code: "invalid_shape",
|
|
454
|
+
message: `${key} must be an array of strings.`,
|
|
455
|
+
path: `$.${key}`
|
|
456
|
+
});
|
|
457
|
+
return [];
|
|
458
|
+
}
|
|
459
|
+
return value;
|
|
460
|
+
}
|
|
461
|
+
function validateToolNames(toolNames, knownToolNames, issues, path) {
|
|
462
|
+
for (const toolName of toolNames) if (!knownToolNames.has(toolName)) issues.push({
|
|
463
|
+
code: "unknown_tool",
|
|
464
|
+
message: `Unknown MCP tool name ${toolName}.`,
|
|
465
|
+
path,
|
|
466
|
+
toolName
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
function validateToolCards(value, knownToolNames, issues) {
|
|
470
|
+
if (!isRecord(value)) {
|
|
471
|
+
issues.push({
|
|
472
|
+
code: "invalid_tool_card",
|
|
473
|
+
message: "toolCards must be an object keyed by tool name.",
|
|
474
|
+
path: "$.toolCards"
|
|
475
|
+
});
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
for (const [toolName, card] of Object.entries(value)) {
|
|
479
|
+
if (!knownToolNames.has(toolName)) issues.push({
|
|
480
|
+
code: "unknown_tool",
|
|
481
|
+
message: `toolCards references unknown MCP tool name ${toolName}.`,
|
|
482
|
+
path: `$.toolCards.${toolName}`,
|
|
483
|
+
toolName
|
|
484
|
+
});
|
|
485
|
+
if (!isRecord(card) || !isString(card.summary)) {
|
|
486
|
+
issues.push({
|
|
487
|
+
code: "invalid_tool_card",
|
|
488
|
+
message: `toolCards.${toolName} must include a string summary.`,
|
|
489
|
+
path: `$.toolCards.${toolName}`,
|
|
490
|
+
toolName
|
|
491
|
+
});
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
if (card.title !== void 0 && !isString(card.title)) issues.push({
|
|
495
|
+
code: "invalid_tool_card",
|
|
496
|
+
message: `toolCards.${toolName}.title must be a string when provided.`,
|
|
497
|
+
path: `$.toolCards.${toolName}.title`,
|
|
498
|
+
toolName
|
|
499
|
+
});
|
|
500
|
+
if (card.keywords !== void 0 && (!Array.isArray(card.keywords) || !card.keywords.every((keyword) => isString(keyword)))) issues.push({
|
|
501
|
+
code: "invalid_tool_card",
|
|
502
|
+
message: `toolCards.${toolName}.keywords must be an array of strings when provided.`,
|
|
503
|
+
path: `$.toolCards.${toolName}.keywords`,
|
|
504
|
+
toolName
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
function validateSkillChapters(value, issues) {
|
|
509
|
+
if (value === void 0) return;
|
|
510
|
+
if (!Array.isArray(value)) {
|
|
511
|
+
issues.push({
|
|
512
|
+
code: "invalid_skill_chapter",
|
|
513
|
+
message: "skillChapters must be an array when provided.",
|
|
514
|
+
path: "$.skillChapters"
|
|
515
|
+
});
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
for (const [index, chapter] of value.entries()) if (!isRecord(chapter) || !isString(chapter.id) || !isString(chapter.title) || !isString(chapter.summary)) issues.push({
|
|
519
|
+
code: "invalid_skill_chapter",
|
|
520
|
+
message: "Each skill chapter must include string id, title, and summary.",
|
|
521
|
+
path: `$.skillChapters.${index}`
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
function uniqueSorted(values) {
|
|
525
|
+
return [...new Set(values)].toSorted();
|
|
526
|
+
}
|
|
527
|
+
function optionalUniqueSorted(values) {
|
|
528
|
+
return values === void 0 ? void 0 : uniqueSorted(values);
|
|
529
|
+
}
|
|
530
|
+
function cloneToolCards(cards) {
|
|
531
|
+
return Object.fromEntries(Object.entries(cards).toSorted(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([toolName, card]) => [toolName, {
|
|
532
|
+
...card,
|
|
533
|
+
keywords: card.keywords === void 0 ? void 0 : [...card.keywords]
|
|
534
|
+
}]));
|
|
535
|
+
}
|
|
536
|
+
function assertProfileServerMatchesManifest(manifest, learnedProfile, label) {
|
|
537
|
+
if (learnedProfile !== void 0 && learnedProfile.serverId !== manifest.server.id) throw new Error(`${label} server ${learnedProfile.serverId} does not match manifest server ${manifest.server.id}`);
|
|
538
|
+
}
|
|
539
|
+
function assertOverlayServerMatchesManifest(manifest, runtimeOverlay) {
|
|
540
|
+
if (runtimeOverlay !== void 0 && runtimeOverlay.serverId !== manifest.server.id) throw new Error(`runtimeOverlay server ${runtimeOverlay.serverId} does not match manifest server ${manifest.server.id}`);
|
|
541
|
+
}
|
|
542
|
+
function mergeSkillChapters(learnedChapters, manifestChapters, overlayChapters) {
|
|
543
|
+
const chapters = /* @__PURE__ */ new Map();
|
|
544
|
+
for (const chapter of [
|
|
545
|
+
...learnedChapters ?? [],
|
|
546
|
+
...manifestChapters ?? [],
|
|
547
|
+
...overlayChapters ?? []
|
|
548
|
+
]) chapters.set(chapter.id, { ...chapter });
|
|
549
|
+
return [...chapters.values()].toSorted((left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0);
|
|
550
|
+
}
|
|
206
551
|
|
|
207
552
|
//#endregion
|
|
208
|
-
export { ExposurePlanner, McpPlusWrapperRuntime, compileMcpPlusManifest, createExpandToolDeclaration, defineMcpPlusManifest, estimateExposurePlanImpact, lowerExposurePlanToMcpSurface, planExposure };
|
|
553
|
+
export { ExposurePlanner, MCP_PLUS_PROFILE_SCHEMA_VERSION, McpPlusWrapperRuntime, compileMcpPlusManifest, createExpandToolDeclaration, createInitToolDeclaration, createLearnedProfileFromProposal, createReprofileToolDeclaration, defineMcpPlusManifest, estimateExposurePlanImpact, lowerExposurePlanToMcpSurface, mergeManifestWithProfileProposal, mergeMcpPlusPolicy, normalizeProfileProposal, planExposure, validateProfileProposal };
|
|
209
554
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["graph: ExposureGraph","#state","#matchTools"],"sources":["../src/index.ts"],"sourcesContent":["export type JsonSchema = {\n type?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n additionalProperties?: boolean;\n description?: string;\n enum?: string[];\n items?: JsonSchema;\n [key: string]: unknown;\n};\n\nexport type NativeToolDeclaration = {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n};\n\nexport type McpPlusServerManifest = {\n id: string;\n title?: string;\n summary: string;\n};\n\nexport type McpPlusExposurePolicy = {\n pinnedTools?: string[];\n warmTools?: string[];\n indexedTools?: string[];\n alwaysIndexTools?: string[];\n toolCards?: Record<string, ToolCardPolicy>;\n freezeAfterUnusedTurns?: number;\n warmAfterConsecutiveCalls?: number;\n demoteAfterUnusedTurns?: number;\n};\n\nexport type ToolCardPolicy = {\n title?: string;\n summary?: string;\n keywords?: string[];\n};\n\nexport type McpPlusSkillChapter = {\n id: string;\n title: string;\n summary: string;\n};\n\nexport type McpPlusSkillPolicy = {\n storage?: string;\n chapters?: McpPlusSkillChapter[];\n};\n\nexport type McpPlusManifest = {\n server: McpPlusServerManifest;\n exposure?: McpPlusExposurePolicy;\n skills?: McpPlusSkillPolicy;\n};\n\nexport function defineMcpPlusManifest<const TManifest extends McpPlusManifest>(manifest: TManifest): TManifest {\n return manifest;\n}\n\nexport type CapabilityActivation = {\n serverId: string;\n toolName: string;\n};\n\nexport type ToolIndexEntry = {\n id: string;\n title: string;\n summary: string;\n activation: CapabilityActivation;\n pinned: boolean;\n};\n\nexport type SkillIndexEntry = {\n id: string;\n title: string;\n summary: string;\n serverId: string;\n whenToUse?: string;\n why?: string;\n pitfallsPreview?: string[];\n};\n\nexport type ServerCard = {\n id: string;\n title: string;\n summary: string;\n mode: ExposureMode;\n};\n\nexport type ExposureMode = 'expanded' | 'indexed' | 'frozen';\n\nexport type ExposureGraph = {\n server: McpPlusServerManifest;\n tools: NativeToolDeclaration[];\n pinnedToolNames: Set<string>;\n warmToolNames: Set<string>;\n indexedToolNames: Set<string>;\n alwaysIndexToolNames: Set<string>;\n toolCards: Record<string, ToolCardPolicy>;\n skillIndex: SkillIndexEntry[];\n policy: Required<Pick<McpPlusExposurePolicy, 'freezeAfterUnusedTurns' | 'warmAfterConsecutiveCalls' | 'demoteAfterUnusedTurns'>>;\n};\n\nexport type ExposureState = {\n serverId: string;\n mode: ExposureMode;\n activeTools?: string[];\n};\n\nexport type ExposurePlan = {\n serverCard: ServerCard;\n visibleTools: NativeToolDeclaration[];\n toolIndex: ToolIndexEntry[];\n skillIndex: SkillIndexEntry[];\n};\n\nexport type McpPlusSidecar = {\n serverCard: ServerCard;\n toolIndex: ToolIndexEntry[];\n skillIndex: SkillIndexEntry[];\n};\n\nexport type McpCompatibleSurface = {\n tools: NativeToolDeclaration[];\n sidecar: McpPlusSidecar;\n};\n\nexport type ExposureImpactEstimate = {\n nativeToolCount: number;\n visibleToolCount: number;\n indexedToolCount: number;\n fullSchemaCharacters: number;\n visibleSchemaCharacters: number;\n foldedContextCharacters: number;\n schemaCharacterSavings: number;\n indexedActivationTurns: number;\n stableIndexCharacters: number;\n};\n\nexport type ExpandRequest = {\n server?: string;\n request: string;\n};\n\nexport type ExpandResult = {\n serverId: string;\n activatedTools: string[];\n mode: ExposureMode;\n};\n\nconst DEFAULT_FREEZE_AFTER_UNUSED_TURNS = 5;\nconst DEFAULT_WARM_AFTER_CONSECUTIVE_CALLS = 2;\nconst DEFAULT_DEMOTE_AFTER_UNUSED_TURNS = 2;\n\nexport function compileMcpPlusManifest(manifest: McpPlusManifest, nativeTools: NativeToolDeclaration[]): ExposureGraph {\n const pinnedToolNames = new Set(manifest.exposure?.pinnedTools);\n const warmToolNames = new Set(manifest.exposure?.warmTools);\n const alwaysIndexToolNames = new Set(manifest.exposure?.alwaysIndexTools);\n const indexedToolNames = new Set([...(manifest.exposure?.indexedTools ?? []), ...alwaysIndexToolNames]);\n\n for (const tool of nativeTools) {\n if (!pinnedToolNames.has(tool.name) && !warmToolNames.has(tool.name)) {\n indexedToolNames.add(tool.name);\n }\n }\n\n return {\n server: manifest.server,\n tools: nativeTools.toSorted(compareByName),\n pinnedToolNames,\n warmToolNames,\n indexedToolNames,\n alwaysIndexToolNames,\n toolCards: manifest.exposure?.toolCards ?? {},\n skillIndex: (manifest.skills?.chapters ?? []).map(chapter => ({\n id: chapter.id,\n title: chapter.title,\n summary: chapter.summary,\n serverId: manifest.server.id\n })),\n policy: {\n freezeAfterUnusedTurns: manifest.exposure?.freezeAfterUnusedTurns ?? DEFAULT_FREEZE_AFTER_UNUSED_TURNS,\n warmAfterConsecutiveCalls: manifest.exposure?.warmAfterConsecutiveCalls ?? DEFAULT_WARM_AFTER_CONSECUTIVE_CALLS,\n demoteAfterUnusedTurns: manifest.exposure?.demoteAfterUnusedTurns ?? DEFAULT_DEMOTE_AFTER_UNUSED_TURNS\n }\n };\n}\n\nexport function planExposure(graph: ExposureGraph, state: ExposureState): ExposurePlan {\n if (state.serverId !== graph.server.id) {\n throw new Error(`Exposure state server ${state.serverId} does not match graph server ${graph.server.id}`);\n }\n\n const serverCard = createServerCard(graph, state.mode);\n const expandTool = createExpandToolDeclaration();\n\n if (state.mode === 'frozen') {\n return {\n serverCard,\n visibleTools: [expandTool],\n toolIndex: [],\n skillIndex: []\n };\n }\n\n if (state.mode === 'indexed') {\n return {\n serverCard,\n visibleTools: [expandTool],\n toolIndex: graph.tools.map(tool => createToolIndexEntry(graph.server.id, graph.pinnedToolNames, graph.toolCards, tool)),\n skillIndex: graph.skillIndex\n };\n }\n\n const activeToolNames = new Set(state.activeTools);\n const visibleToolNames = new Set<string>([...graph.pinnedToolNames, ...graph.warmToolNames, ...activeToolNames]);\n for (const toolName of graph.alwaysIndexToolNames) {\n visibleToolNames.delete(toolName);\n }\n const visibleNativeTools = graph.tools.filter(tool => visibleToolNames.has(tool.name));\n const visibleTools = [...visibleNativeTools, expandTool];\n const toolIndex = graph.tools\n .filter(tool => !visibleToolNames.has(tool.name))\n .map(tool => createToolIndexEntry(graph.server.id, graph.pinnedToolNames, graph.toolCards, tool));\n\n return {\n serverCard,\n visibleTools,\n toolIndex,\n skillIndex: graph.skillIndex\n };\n}\n\nexport function createExpandToolDeclaration(): NativeToolDeclaration {\n return {\n name: 'mcp_plus.expand',\n description: 'Ask MCP+ to activate folded MCP tools or skill guidance for a server.',\n inputSchema: {\n type: 'object',\n properties: {\n server: {\n type: 'string',\n description: 'Optional MCP server id to expand.'\n },\n request: {\n type: 'string',\n description: 'Natural-language capability request to match against the MCP+ index.'\n }\n },\n required: ['request'],\n additionalProperties: false\n }\n };\n}\n\nexport function lowerExposurePlanToMcpSurface(plan: ExposurePlan): McpCompatibleSurface {\n return {\n tools: plan.visibleTools,\n sidecar: {\n serverCard: plan.serverCard,\n toolIndex: plan.toolIndex,\n skillIndex: plan.skillIndex\n }\n };\n}\n\nexport function estimateExposurePlanImpact(graph: ExposureGraph, plan: ExposurePlan): ExposureImpactEstimate {\n const fullSchemaCharacters = JSON.stringify(graph.tools).length;\n const visibleSchemaCharacters = JSON.stringify(plan.visibleTools).length;\n const stableIndexCharacters = JSON.stringify(plan.toolIndex).length;\n const foldedContextCharacters = visibleSchemaCharacters + stableIndexCharacters;\n\n return {\n nativeToolCount: graph.tools.length,\n visibleToolCount: plan.visibleTools.length,\n indexedToolCount: plan.toolIndex.length,\n fullSchemaCharacters,\n visibleSchemaCharacters,\n foldedContextCharacters,\n schemaCharacterSavings: fullSchemaCharacters - foldedContextCharacters,\n indexedActivationTurns: plan.toolIndex.length > 0 ? 2 : 1,\n stableIndexCharacters\n };\n}\n\nexport class ExposurePlanner {\n public constructor(private readonly graph: ExposureGraph) {}\n\n public plan(state: ExposureState): ExposurePlan {\n return planExposure(this.graph, state);\n }\n}\n\nexport class McpPlusWrapperRuntime {\n #state: ExposureState;\n\n public constructor(\n private readonly graph: ExposureGraph,\n initialState?: Partial<ExposureState>\n ) {\n this.#state = {\n serverId: graph.server.id,\n mode: initialState?.mode ?? 'expanded',\n activeTools: initialState?.activeTools ?? []\n };\n }\n\n public getSurface(): McpCompatibleSurface {\n return lowerExposurePlanToMcpSurface(planExposure(this.graph, this.#state));\n }\n\n public expand(request: ExpandRequest): ExpandResult {\n if (request.server !== undefined && request.server !== this.graph.server.id) {\n return {\n serverId: this.graph.server.id,\n activatedTools: [],\n mode: this.#state.mode\n };\n }\n\n const matchedTools = this.#matchTools(request);\n const thawableTools = matchedTools.filter(toolName => !this.graph.alwaysIndexToolNames.has(toolName));\n const activatedTools = thawableTools.filter(toolName => !this.graph.pinnedToolNames.has(toolName));\n if (thawableTools.length === 0 && request.server === undefined) {\n return {\n serverId: this.graph.server.id,\n activatedTools,\n mode: this.#state.mode\n };\n }\n\n this.#state = {\n serverId: this.graph.server.id,\n mode: 'expanded',\n activeTools: mergeToolNames(this.#state.activeTools, activatedTools)\n };\n\n return {\n serverId: this.graph.server.id,\n activatedTools,\n mode: this.#state.mode\n };\n }\n\n #matchTools(request: ExpandRequest): string[] {\n if (request.server !== undefined && request.server !== this.graph.server.id) {\n return [];\n }\n\n const normalizedRequest = normalizeSearchText(request.request);\n const matches = this.graph.tools\n .filter(tool => {\n const card = this.graph.toolCards[tool.name];\n const haystack = normalizeSearchText(\n `${tool.name} ${tool.description} ${card?.title ?? ''} ${card?.summary ?? ''} ${(card?.keywords ?? []).join(' ')}`\n );\n return hasSearchOverlap(normalizedRequest, haystack);\n })\n .map(tool => tool.name);\n\n return matches;\n }\n}\n\nfunction createServerCard(graph: ExposureGraph, mode: ExposureMode): ServerCard {\n return {\n id: graph.server.id,\n title: graph.server.title ?? graph.server.id,\n summary: graph.server.summary,\n mode\n };\n}\n\nfunction createToolIndexEntry(\n serverId: string,\n pinnedToolNames: ReadonlySet<string>,\n toolCards: Readonly<Record<string, ToolCardPolicy>>,\n tool: NativeToolDeclaration\n): ToolIndexEntry {\n const card = toolCards[tool.name];\n\n return {\n id: tool.name,\n title: card?.title ?? tool.name,\n summary: card?.summary ?? tool.description,\n activation: {\n serverId,\n toolName: tool.name\n },\n pinned: pinnedToolNames.has(tool.name)\n };\n}\n\nfunction compareByName(left: NativeToolDeclaration, right: NativeToolDeclaration): number {\n return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;\n}\n\nfunction mergeToolNames(current: readonly string[] | undefined, next: readonly string[]): string[] {\n return [...new Set([...(current ?? []), ...next])].toSorted();\n}\n\nfunction normalizeSearchText(value: string): string {\n return value.toLowerCase().replaceAll(/[^\\p{L}\\p{N}.]+/gu, ' ');\n}\n\nfunction hasSearchOverlap(request: string, haystack: string): boolean {\n const requestTerms = request.split(' ').filter(term => isMeaningfulSearchTerm(term));\n const haystackTerms = haystack.split(' ').filter(term => isMeaningfulSearchTerm(term));\n\n return requestTerms.some(requestTerm =>\n haystackTerms.some(haystackTerm => requestTerm.includes(haystackTerm) || haystackTerm.includes(requestTerm))\n );\n}\n\nfunction isMeaningfulSearchTerm(term: string): boolean {\n if (term === '') {\n return false;\n }\n\n return [...term].some(character => (character.codePointAt(0) ?? 0) > 0x7f) || term.length >= 3;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["issues: ProfileProposalValidationIssue[]","toolCards: Record<string, McpPlusProfileToolCard>","graph: ExposureGraph","#state","#matchTools"],"sources":["../src/index.ts"],"sourcesContent":["export type JsonSchema = {\n type?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n additionalProperties?: boolean | JsonSchema;\n description?: string;\n enum?: string[];\n items?: JsonSchema;\n [key: string]: unknown;\n};\n\nexport type NativeToolDeclaration = {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n};\n\nexport type McpPlusServerManifest = {\n id: string;\n title?: string;\n summary: string;\n};\n\nexport type McpPlusExposurePolicy = {\n pinnedTools?: string[];\n warmTools?: string[];\n indexedTools?: string[];\n alwaysIndexTools?: string[];\n toolCards?: Record<string, ToolCardPolicy>;\n freezeAfterUnusedTurns?: number;\n warmAfterConsecutiveCalls?: number;\n demoteAfterUnusedTurns?: number;\n};\n\nexport type ToolCardPolicy = {\n title?: string;\n summary?: string;\n keywords?: string[];\n};\n\nexport type McpPlusSkillChapter = {\n id: string;\n title: string;\n summary: string;\n};\n\nexport type McpPlusSkillPolicy = {\n storage?: string;\n chapters?: McpPlusSkillChapter[];\n};\n\nexport type McpPlusManifest = {\n server: McpPlusServerManifest;\n exposure?: McpPlusExposurePolicy;\n skills?: McpPlusSkillPolicy;\n};\n\nexport function defineMcpPlusManifest<const TManifest extends McpPlusManifest>(manifest: TManifest): TManifest {\n return manifest;\n}\n\nexport type CapabilityActivation = {\n serverId: string;\n toolName: string;\n};\n\nexport type ToolIndexEntry = {\n id: string;\n title: string;\n summary: string;\n activation: CapabilityActivation;\n pinned: boolean;\n};\n\nexport type SkillIndexEntry = {\n id: string;\n title: string;\n summary: string;\n serverId: string;\n whenToUse?: string;\n why?: string;\n pitfallsPreview?: string[];\n};\n\nexport type ServerCard = {\n id: string;\n title: string;\n summary: string;\n mode: ExposureMode;\n};\n\nexport type ExposureMode = 'expanded' | 'indexed' | 'frozen';\n\nexport type ExposureGraph = {\n server: McpPlusServerManifest;\n tools: NativeToolDeclaration[];\n pinnedToolNames: Set<string>;\n warmToolNames: Set<string>;\n indexedToolNames: Set<string>;\n alwaysIndexToolNames: Set<string>;\n toolCards: Record<string, ToolCardPolicy>;\n skillIndex: SkillIndexEntry[];\n policy: Required<Pick<McpPlusExposurePolicy, 'freezeAfterUnusedTurns' | 'warmAfterConsecutiveCalls' | 'demoteAfterUnusedTurns'>>;\n};\n\nexport type ExposureState = {\n serverId: string;\n mode: ExposureMode;\n activeTools?: string[];\n};\n\nexport type ExposurePlan = {\n serverCard: ServerCard;\n visibleTools: NativeToolDeclaration[];\n toolIndex: ToolIndexEntry[];\n skillIndex: SkillIndexEntry[];\n};\n\nexport type McpPlusSidecar = {\n serverCard: ServerCard;\n toolIndex: ToolIndexEntry[];\n skillIndex: SkillIndexEntry[];\n};\n\nexport type McpCompatibleSurface = {\n tools: NativeToolDeclaration[];\n sidecar: McpPlusSidecar;\n};\n\nexport type ExposureImpactEstimate = {\n nativeToolCount: number;\n visibleToolCount: number;\n indexedToolCount: number;\n fullSchemaCharacters: number;\n visibleSchemaCharacters: number;\n foldedContextCharacters: number;\n schemaCharacterSavings: number;\n indexedActivationTurns: number;\n stableIndexCharacters: number;\n};\n\nexport type ExpandRequest = {\n server?: string;\n request: string;\n};\n\nexport type ExpandResult = {\n serverId: string;\n activatedTools: string[];\n mode: ExposureMode;\n};\n\nexport const MCP_PLUS_PROFILE_SCHEMA_VERSION = 'mcp-plus.profile.v1' as const;\n\nexport type McpPlusProfileSchemaVersion = typeof MCP_PLUS_PROFILE_SCHEMA_VERSION;\n\nexport type McpPlusProfileToolCard = {\n title?: string;\n summary: string;\n keywords?: string[];\n};\n\nexport type McpPlusProfileProposal = {\n serverId: string;\n pinnedTools: string[];\n warmTools?: string[];\n indexedTools: string[];\n alwaysIndexTools?: string[];\n toolCards: Record<string, McpPlusProfileToolCard>;\n skillChapters?: McpPlusSkillChapter[];\n rationale?: Record<string, string>;\n modeHint?: never;\n};\n\nexport type McpPlusLearnedProfile = {\n schemaVersion: McpPlusProfileSchemaVersion;\n serverId: string;\n pinnedTools?: string[];\n warmTools?: string[];\n indexedTools?: string[];\n alwaysIndexTools?: string[];\n toolCards?: Record<string, McpPlusProfileToolCard>;\n skillChapters?: McpPlusSkillChapter[];\n rationale?: Record<string, string>;\n};\n\nexport type McpPlusRuntimeOverlay = {\n serverId: string;\n sessionId?: string;\n exposure?: McpPlusExposurePolicy;\n skills?: McpPlusSkillPolicy;\n state?: {\n mode?: ExposureMode;\n activeTools?: string[];\n pendingReprofile?: boolean;\n counters?: Record<string, number>;\n };\n};\n\nexport type ProfileProposalValidationIssueCode =\n | 'invalid_shape'\n | 'server_mismatch'\n | 'unknown_tool'\n | 'always_index_pinned'\n | 'invalid_tool_card'\n | 'invalid_skill_chapter'\n | 'reserved_runtime_field';\n\nexport type ProfileProposalValidationIssue = {\n code: ProfileProposalValidationIssueCode;\n message: string;\n path: string;\n toolName?: string;\n};\n\nexport type ProfileProposalValidationOptions = {\n serverId?: string;\n alwaysIndexTools?: readonly string[];\n};\n\nexport type ProfileProposalValidationResult = {\n valid: boolean;\n issues: ProfileProposalValidationIssue[];\n};\n\nexport type MergeMcpPlusPolicyInput = {\n manifest: McpPlusManifest;\n learnedProfile?: McpPlusLearnedProfile;\n runtimeOverlay?: McpPlusRuntimeOverlay;\n};\n\nconst DEFAULT_FREEZE_AFTER_UNUSED_TURNS = 5;\nconst DEFAULT_WARM_AFTER_CONSECUTIVE_CALLS = 2;\nconst DEFAULT_DEMOTE_AFTER_UNUSED_TURNS = 2;\n\nexport function createInitToolDeclaration(): NativeToolDeclaration {\n return {\n name: 'mcp_plus.init',\n description: [\n 'Submit an initial MCP+ exposure profile proposal for this standard MCP server.',\n 'Use only tool names from the current tools/list result.',\n 'Do not include runtime exposure mode; expanded/indexed/frozen is host-owned session state.'\n ].join(' '),\n inputSchema: createProfileProposalInputSchema('Initial profile proposal to validate.')\n };\n}\n\nexport function createReprofileToolDeclaration(): NativeToolDeclaration {\n return {\n name: 'mcp_plus.reprofile',\n description: [\n 'Submit an updated MCP+ exposure profile proposal after host-selected reprofile.',\n 'Use only tool names from the current tools/list result.',\n 'This is a proposal only; the host decides whether to accept, merge, and persist it.'\n ].join(' '),\n inputSchema: createProfileProposalInputSchema('Updated profile proposal to validate.')\n };\n}\n\nexport function validateProfileProposal(\n proposal: unknown,\n nativeTools: readonly NativeToolDeclaration[],\n options: ProfileProposalValidationOptions = {}\n): ProfileProposalValidationResult {\n const issues: ProfileProposalValidationIssue[] = [];\n const knownToolNames = new Set(nativeTools.map(tool => tool.name));\n\n if (!isRecord(proposal)) {\n return {\n valid: false,\n issues: [\n {\n code: 'invalid_shape',\n message: 'Profile proposal must be an object.',\n path: '$'\n }\n ]\n };\n }\n\n if ('modeHint' in proposal) {\n issues.push({\n code: 'reserved_runtime_field',\n message: 'modeHint is runtime overlay state and is not allowed in McpPlusProfileProposal v1.',\n path: '$.modeHint'\n });\n }\n\n if (!isString(proposal.serverId)) {\n issues.push({\n code: 'invalid_shape',\n message: 'serverId must be a string.',\n path: '$.serverId'\n });\n } else if (options.serverId !== undefined && proposal.serverId !== options.serverId) {\n issues.push({\n code: 'server_mismatch',\n message: `Profile proposal serverId ${proposal.serverId} does not match expected server ${options.serverId}.`,\n path: '$.serverId'\n });\n }\n\n const pinnedTools = readStringArray(proposal, 'pinnedTools', issues, true);\n const warmTools = readStringArray(proposal, 'warmTools', issues, false);\n const indexedTools = readStringArray(proposal, 'indexedTools', issues, true);\n const alwaysIndexTools = readStringArray(proposal, 'alwaysIndexTools', issues, false);\n const protectedAlwaysIndexTools = new Set([...(options.alwaysIndexTools ?? []), ...alwaysIndexTools]);\n\n validateToolNames(pinnedTools, knownToolNames, issues, '$.pinnedTools');\n validateToolNames(warmTools, knownToolNames, issues, '$.warmTools');\n validateToolNames(indexedTools, knownToolNames, issues, '$.indexedTools');\n validateToolNames(alwaysIndexTools, knownToolNames, issues, '$.alwaysIndexTools');\n\n for (const toolName of pinnedTools) {\n if (protectedAlwaysIndexTools.has(toolName)) {\n issues.push({\n code: 'always_index_pinned',\n message: `Tool ${toolName} is always-index and cannot be pinned by a profile proposal.`,\n path: '$.pinnedTools',\n toolName\n });\n }\n }\n\n validateToolCards(proposal.toolCards, knownToolNames, issues);\n validateSkillChapters(proposal.skillChapters, issues);\n\n return {\n valid: issues.length === 0,\n issues\n };\n}\n\nexport function normalizeProfileProposal(proposal: McpPlusProfileProposal): McpPlusProfileProposal {\n return {\n serverId: proposal.serverId,\n pinnedTools: uniqueSorted(proposal.pinnedTools),\n warmTools: optionalUniqueSorted(proposal.warmTools),\n indexedTools: uniqueSorted(proposal.indexedTools),\n alwaysIndexTools: optionalUniqueSorted(proposal.alwaysIndexTools),\n toolCards: cloneToolCards(proposal.toolCards),\n skillChapters: proposal.skillChapters?.map(chapter => ({ ...chapter })),\n rationale: proposal.rationale === undefined ? undefined : { ...proposal.rationale }\n };\n}\n\nexport function createLearnedProfileFromProposal(proposal: McpPlusProfileProposal): McpPlusLearnedProfile {\n const normalized = normalizeProfileProposal(proposal);\n\n return {\n schemaVersion: MCP_PLUS_PROFILE_SCHEMA_VERSION,\n serverId: normalized.serverId,\n pinnedTools: normalized.pinnedTools,\n warmTools: normalized.warmTools,\n indexedTools: normalized.indexedTools,\n alwaysIndexTools: normalized.alwaysIndexTools,\n toolCards: normalized.toolCards,\n skillChapters: normalized.skillChapters,\n rationale: normalized.rationale\n };\n}\n\nexport function mergeManifestWithProfileProposal(\n manifest: McpPlusManifest,\n proposal: McpPlusProfileProposal,\n options: { runtimeOverlay?: McpPlusRuntimeOverlay } = {}\n): McpPlusManifest {\n return mergeMcpPlusPolicy({\n manifest,\n learnedProfile: createLearnedProfileFromProposal(proposal),\n runtimeOverlay: options.runtimeOverlay\n });\n}\n\nexport function mergeMcpPlusPolicy(input: MergeMcpPlusPolicyInput): McpPlusManifest {\n const manifest = input.manifest;\n const learnedProfile = input.learnedProfile;\n const runtimeOverlay = input.runtimeOverlay;\n const manifestExposure = manifest.exposure ?? {};\n const overlayExposure = runtimeOverlay?.exposure ?? {};\n\n assertProfileServerMatchesManifest(manifest, learnedProfile, 'learnedProfile');\n assertOverlayServerMatchesManifest(manifest, runtimeOverlay);\n\n const alwaysIndexTools = uniqueSorted([\n ...(manifestExposure.alwaysIndexTools ?? []),\n ...(learnedProfile?.alwaysIndexTools ?? []),\n ...(overlayExposure.alwaysIndexTools ?? [])\n ]);\n const alwaysIndexToolSet = new Set(alwaysIndexTools);\n const pinnedTools = uniqueSorted([\n ...(manifestExposure.pinnedTools ?? []),\n ...(learnedProfile?.pinnedTools ?? []).filter(toolName => !alwaysIndexToolSet.has(toolName)),\n ...(overlayExposure.pinnedTools ?? []).filter(toolName => !alwaysIndexToolSet.has(toolName))\n ]);\n const warmTools = uniqueSorted([\n ...(manifestExposure.warmTools ?? []),\n ...(learnedProfile?.warmTools ?? []).filter(toolName => !alwaysIndexToolSet.has(toolName)),\n ...(overlayExposure.warmTools ?? []).filter(toolName => !alwaysIndexToolSet.has(toolName))\n ]);\n const indexedTools = uniqueSorted([\n ...(manifestExposure.indexedTools ?? []),\n ...(learnedProfile?.indexedTools ?? []),\n ...(overlayExposure.indexedTools ?? []),\n ...alwaysIndexTools\n ]);\n const toolCards: Record<string, McpPlusProfileToolCard> = Object.assign(\n {},\n learnedProfile?.toolCards,\n manifestExposure.toolCards,\n overlayExposure.toolCards\n );\n const skillChapters = mergeSkillChapters(learnedProfile?.skillChapters, manifest.skills?.chapters, runtimeOverlay?.skills?.chapters);\n\n return {\n server: { ...manifest.server },\n exposure: {\n ...manifestExposure,\n ...overlayExposure,\n pinnedTools,\n warmTools,\n indexedTools,\n alwaysIndexTools,\n toolCards\n },\n skills:\n manifest.skills === undefined && runtimeOverlay?.skills === undefined && skillChapters.length === 0\n ? undefined\n : Object.assign({}, manifest.skills, runtimeOverlay?.skills, { chapters: skillChapters })\n };\n}\n\nexport function compileMcpPlusManifest(manifest: McpPlusManifest, nativeTools: NativeToolDeclaration[]): ExposureGraph {\n const pinnedToolNames = new Set(manifest.exposure?.pinnedTools);\n const warmToolNames = new Set(manifest.exposure?.warmTools);\n const alwaysIndexToolNames = new Set(manifest.exposure?.alwaysIndexTools);\n const indexedToolNames = new Set([...(manifest.exposure?.indexedTools ?? []), ...alwaysIndexToolNames]);\n\n for (const tool of nativeTools) {\n if (!pinnedToolNames.has(tool.name) && !warmToolNames.has(tool.name)) {\n indexedToolNames.add(tool.name);\n }\n }\n\n return {\n server: manifest.server,\n tools: nativeTools.toSorted(compareByName),\n pinnedToolNames,\n warmToolNames,\n indexedToolNames,\n alwaysIndexToolNames,\n toolCards: manifest.exposure?.toolCards ?? {},\n skillIndex: (manifest.skills?.chapters ?? []).map(chapter => ({\n id: chapter.id,\n title: chapter.title,\n summary: chapter.summary,\n serverId: manifest.server.id\n })),\n policy: {\n freezeAfterUnusedTurns: manifest.exposure?.freezeAfterUnusedTurns ?? DEFAULT_FREEZE_AFTER_UNUSED_TURNS,\n warmAfterConsecutiveCalls: manifest.exposure?.warmAfterConsecutiveCalls ?? DEFAULT_WARM_AFTER_CONSECUTIVE_CALLS,\n demoteAfterUnusedTurns: manifest.exposure?.demoteAfterUnusedTurns ?? DEFAULT_DEMOTE_AFTER_UNUSED_TURNS\n }\n };\n}\n\nexport function planExposure(graph: ExposureGraph, state: ExposureState): ExposurePlan {\n if (state.serverId !== graph.server.id) {\n throw new Error(`Exposure state server ${state.serverId} does not match graph server ${graph.server.id}`);\n }\n\n const serverCard = createServerCard(graph, state.mode);\n const expandTool = createExpandToolDeclaration();\n\n if (state.mode === 'frozen') {\n return {\n serverCard,\n visibleTools: [expandTool],\n toolIndex: [],\n skillIndex: []\n };\n }\n\n if (state.mode === 'indexed') {\n return {\n serverCard,\n visibleTools: [expandTool],\n toolIndex: graph.tools.map(tool => createToolIndexEntry(graph.server.id, graph.pinnedToolNames, graph.toolCards, tool)),\n skillIndex: graph.skillIndex\n };\n }\n\n const activeToolNames = new Set(state.activeTools);\n const visibleToolNames = new Set<string>([...graph.pinnedToolNames, ...graph.warmToolNames, ...activeToolNames]);\n for (const toolName of graph.alwaysIndexToolNames) {\n visibleToolNames.delete(toolName);\n }\n const visibleNativeTools = graph.tools.filter(tool => visibleToolNames.has(tool.name));\n const visibleTools = [...visibleNativeTools, expandTool];\n const toolIndex = graph.tools\n .filter(tool => !visibleToolNames.has(tool.name))\n .map(tool => createToolIndexEntry(graph.server.id, graph.pinnedToolNames, graph.toolCards, tool));\n\n return {\n serverCard,\n visibleTools,\n toolIndex,\n skillIndex: graph.skillIndex\n };\n}\n\nexport function createExpandToolDeclaration(): NativeToolDeclaration {\n return {\n name: 'mcp_plus.expand',\n description: 'Ask MCP+ to activate folded MCP tools or skill guidance for a server.',\n inputSchema: {\n type: 'object',\n properties: {\n server: {\n type: 'string',\n description: 'Optional MCP server id to expand.'\n },\n request: {\n type: 'string',\n description: 'Natural-language capability request to match against the MCP+ index.'\n }\n },\n required: ['request'],\n additionalProperties: false\n }\n };\n}\n\nexport function lowerExposurePlanToMcpSurface(plan: ExposurePlan): McpCompatibleSurface {\n return {\n tools: plan.visibleTools,\n sidecar: {\n serverCard: plan.serverCard,\n toolIndex: plan.toolIndex,\n skillIndex: plan.skillIndex\n }\n };\n}\n\nexport function estimateExposurePlanImpact(graph: ExposureGraph, plan: ExposurePlan): ExposureImpactEstimate {\n const fullSchemaCharacters = JSON.stringify(graph.tools).length;\n const visibleSchemaCharacters = JSON.stringify(plan.visibleTools).length;\n const stableIndexCharacters = JSON.stringify(plan.toolIndex).length;\n const foldedContextCharacters = visibleSchemaCharacters + stableIndexCharacters;\n\n return {\n nativeToolCount: graph.tools.length,\n visibleToolCount: plan.visibleTools.length,\n indexedToolCount: plan.toolIndex.length,\n fullSchemaCharacters,\n visibleSchemaCharacters,\n foldedContextCharacters,\n schemaCharacterSavings: fullSchemaCharacters - foldedContextCharacters,\n indexedActivationTurns: plan.toolIndex.length > 0 ? 2 : 1,\n stableIndexCharacters\n };\n}\n\nexport class ExposurePlanner {\n public constructor(private readonly graph: ExposureGraph) {}\n\n public plan(state: ExposureState): ExposurePlan {\n return planExposure(this.graph, state);\n }\n}\n\nexport class McpPlusWrapperRuntime {\n #state: ExposureState;\n\n public constructor(\n private readonly graph: ExposureGraph,\n initialState?: Partial<ExposureState>\n ) {\n this.#state = {\n serverId: graph.server.id,\n mode: initialState?.mode ?? 'expanded',\n activeTools: initialState?.activeTools ?? []\n };\n }\n\n public getSurface(): McpCompatibleSurface {\n return lowerExposurePlanToMcpSurface(planExposure(this.graph, this.#state));\n }\n\n public expand(request: ExpandRequest): ExpandResult {\n if (request.server !== undefined && request.server !== this.graph.server.id) {\n return {\n serverId: this.graph.server.id,\n activatedTools: [],\n mode: this.#state.mode\n };\n }\n\n const matchedTools = this.#matchTools(request);\n const thawableTools = matchedTools.filter(toolName => !this.graph.alwaysIndexToolNames.has(toolName));\n const activatedTools = thawableTools.filter(toolName => !this.graph.pinnedToolNames.has(toolName));\n if (thawableTools.length === 0 && request.server === undefined) {\n return {\n serverId: this.graph.server.id,\n activatedTools,\n mode: this.#state.mode\n };\n }\n\n this.#state = {\n serverId: this.graph.server.id,\n mode: 'expanded',\n activeTools: mergeToolNames(this.#state.activeTools, activatedTools)\n };\n\n return {\n serverId: this.graph.server.id,\n activatedTools,\n mode: this.#state.mode\n };\n }\n\n #matchTools(request: ExpandRequest): string[] {\n if (request.server !== undefined && request.server !== this.graph.server.id) {\n return [];\n }\n\n const normalizedRequest = normalizeSearchText(request.request);\n const matches = this.graph.tools\n .filter(tool => {\n const card = this.graph.toolCards[tool.name];\n const haystack = normalizeSearchText(\n `${tool.name} ${tool.description} ${card?.title ?? ''} ${card?.summary ?? ''} ${(card?.keywords ?? []).join(' ')}`\n );\n return hasSearchOverlap(normalizedRequest, haystack);\n })\n .map(tool => tool.name);\n\n return matches;\n }\n}\n\nfunction createServerCard(graph: ExposureGraph, mode: ExposureMode): ServerCard {\n return {\n id: graph.server.id,\n title: graph.server.title ?? graph.server.id,\n summary: graph.server.summary,\n mode\n };\n}\n\nfunction createToolIndexEntry(\n serverId: string,\n pinnedToolNames: ReadonlySet<string>,\n toolCards: Readonly<Record<string, ToolCardPolicy>>,\n tool: NativeToolDeclaration\n): ToolIndexEntry {\n const card = toolCards[tool.name];\n\n return {\n id: tool.name,\n title: card?.title ?? tool.name,\n summary: card?.summary ?? tool.description,\n activation: {\n serverId,\n toolName: tool.name\n },\n pinned: pinnedToolNames.has(tool.name)\n };\n}\n\nfunction compareByName(left: NativeToolDeclaration, right: NativeToolDeclaration): number {\n return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;\n}\n\nfunction mergeToolNames(current: readonly string[] | undefined, next: readonly string[]): string[] {\n return [...new Set([...(current ?? []), ...next])].toSorted();\n}\n\nfunction normalizeSearchText(value: string): string {\n return value.toLowerCase().replaceAll(/[^\\p{L}\\p{N}.]+/gu, ' ');\n}\n\nfunction hasSearchOverlap(request: string, haystack: string): boolean {\n const requestTerms = request.split(' ').filter(term => isMeaningfulSearchTerm(term));\n const haystackTerms = haystack.split(' ').filter(term => isMeaningfulSearchTerm(term));\n\n return requestTerms.some(requestTerm =>\n haystackTerms.some(haystackTerm => requestTerm.includes(haystackTerm) || haystackTerm.includes(requestTerm))\n );\n}\n\nfunction isMeaningfulSearchTerm(term: string): boolean {\n if (term === '') {\n return false;\n }\n\n return [...term].some(character => (character.codePointAt(0) ?? 0) > 0x7f) || term.length >= 3;\n}\n\nfunction createProfileProposalInputSchema(description: string): JsonSchema {\n return {\n type: 'object',\n description,\n properties: {\n serverId: {\n type: 'string',\n description: 'MCP server id this proposal applies to.'\n },\n pinnedTools: {\n type: 'array',\n description: 'Tool names to keep visible as full schemas when the server is expanded.',\n items: { type: 'string' }\n },\n warmTools: {\n type: 'array',\n description: 'Tool names that may stay visible initially, subject to host-owned demotion policy.',\n items: { type: 'string' }\n },\n indexedTools: {\n type: 'array',\n description: 'Tool names represented by compact capability cards until activated.',\n items: { type: 'string' }\n },\n alwaysIndexTools: {\n type: 'array',\n description: 'Tool names that should remain indexed and must not be automatically pinned.',\n items: { type: 'string' }\n },\n toolCards: {\n type: 'object',\n description: 'Compact capability cards keyed by tool name.',\n additionalProperties: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n summary: { type: 'string' },\n keywords: {\n type: 'array',\n items: { type: 'string' }\n }\n },\n required: ['summary'],\n additionalProperties: false\n }\n },\n skillChapters: {\n type: 'array',\n description: 'Initial compact server-bound skill chapters.',\n items: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n title: { type: 'string' },\n summary: { type: 'string' }\n },\n required: ['id', 'title', 'summary'],\n additionalProperties: false\n }\n },\n rationale: {\n type: 'object',\n description: 'Optional short rationale keyed by tool name or policy area.',\n additionalProperties: { type: 'string' }\n }\n },\n required: ['serverId', 'pinnedTools', 'indexedTools', 'toolCards'],\n additionalProperties: false\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nfunction readStringArray(\n object: Record<string, unknown>,\n key: string,\n issues: ProfileProposalValidationIssue[],\n required: boolean\n): string[] {\n const value = object[key];\n if (value === undefined) {\n if (required) {\n issues.push({\n code: 'invalid_shape',\n message: `${key} must be an array of strings.`,\n path: `$.${key}`\n });\n }\n return [];\n }\n\n if (!Array.isArray(value) || !value.every(item => isString(item))) {\n issues.push({\n code: 'invalid_shape',\n message: `${key} must be an array of strings.`,\n path: `$.${key}`\n });\n return [];\n }\n\n return value;\n}\n\nfunction validateToolNames(\n toolNames: readonly string[],\n knownToolNames: ReadonlySet<string>,\n issues: ProfileProposalValidationIssue[],\n path: string\n): void {\n for (const toolName of toolNames) {\n if (!knownToolNames.has(toolName)) {\n issues.push({\n code: 'unknown_tool',\n message: `Unknown MCP tool name ${toolName}.`,\n path,\n toolName\n });\n }\n }\n}\n\nfunction validateToolCards(value: unknown, knownToolNames: ReadonlySet<string>, issues: ProfileProposalValidationIssue[]): void {\n if (!isRecord(value)) {\n issues.push({\n code: 'invalid_tool_card',\n message: 'toolCards must be an object keyed by tool name.',\n path: '$.toolCards'\n });\n return;\n }\n\n for (const [toolName, card] of Object.entries(value)) {\n if (!knownToolNames.has(toolName)) {\n issues.push({\n code: 'unknown_tool',\n message: `toolCards references unknown MCP tool name ${toolName}.`,\n path: `$.toolCards.${toolName}`,\n toolName\n });\n }\n\n if (!isRecord(card) || !isString(card.summary)) {\n issues.push({\n code: 'invalid_tool_card',\n message: `toolCards.${toolName} must include a string summary.`,\n path: `$.toolCards.${toolName}`,\n toolName\n });\n continue;\n }\n\n if (card.title !== undefined && !isString(card.title)) {\n issues.push({\n code: 'invalid_tool_card',\n message: `toolCards.${toolName}.title must be a string when provided.`,\n path: `$.toolCards.${toolName}.title`,\n toolName\n });\n }\n\n if (card.keywords !== undefined && (!Array.isArray(card.keywords) || !card.keywords.every(keyword => isString(keyword)))) {\n issues.push({\n code: 'invalid_tool_card',\n message: `toolCards.${toolName}.keywords must be an array of strings when provided.`,\n path: `$.toolCards.${toolName}.keywords`,\n toolName\n });\n }\n }\n}\n\nfunction validateSkillChapters(value: unknown, issues: ProfileProposalValidationIssue[]): void {\n if (value === undefined) {\n return;\n }\n\n if (!Array.isArray(value)) {\n issues.push({\n code: 'invalid_skill_chapter',\n message: 'skillChapters must be an array when provided.',\n path: '$.skillChapters'\n });\n return;\n }\n\n for (const [index, chapter] of value.entries()) {\n if (!isRecord(chapter) || !isString(chapter.id) || !isString(chapter.title) || !isString(chapter.summary)) {\n issues.push({\n code: 'invalid_skill_chapter',\n message: 'Each skill chapter must include string id, title, and summary.',\n path: `$.skillChapters.${index}`\n });\n }\n }\n}\n\nfunction uniqueSorted(values: readonly string[]): string[] {\n return [...new Set(values)].toSorted();\n}\n\nfunction optionalUniqueSorted(values: readonly string[] | undefined): string[] | undefined {\n return values === undefined ? undefined : uniqueSorted(values);\n}\n\nfunction cloneToolCards(cards: Record<string, McpPlusProfileToolCard>): Record<string, McpPlusProfileToolCard> {\n return Object.fromEntries(\n Object.entries(cards)\n .toSorted(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))\n .map(([toolName, card]) => [\n toolName,\n {\n ...card,\n keywords: card.keywords === undefined ? undefined : [...card.keywords]\n }\n ])\n );\n}\n\nfunction assertProfileServerMatchesManifest(\n manifest: McpPlusManifest,\n learnedProfile: McpPlusLearnedProfile | undefined,\n label: string\n): void {\n if (learnedProfile !== undefined && learnedProfile.serverId !== manifest.server.id) {\n throw new Error(`${label} server ${learnedProfile.serverId} does not match manifest server ${manifest.server.id}`);\n }\n}\n\nfunction assertOverlayServerMatchesManifest(manifest: McpPlusManifest, runtimeOverlay: McpPlusRuntimeOverlay | undefined): void {\n if (runtimeOverlay !== undefined && runtimeOverlay.serverId !== manifest.server.id) {\n throw new Error(`runtimeOverlay server ${runtimeOverlay.serverId} does not match manifest server ${manifest.server.id}`);\n }\n}\n\nfunction mergeSkillChapters(\n learnedChapters: readonly McpPlusSkillChapter[] | undefined,\n manifestChapters: readonly McpPlusSkillChapter[] | undefined,\n overlayChapters: readonly McpPlusSkillChapter[] | undefined\n): McpPlusSkillChapter[] {\n const chapters = new Map<string, McpPlusSkillChapter>();\n\n for (const chapter of [...(learnedChapters ?? []), ...(manifestChapters ?? []), ...(overlayChapters ?? [])]) {\n chapters.set(chapter.id, { ...chapter });\n }\n\n return [...chapters.values()].toSorted((left, right) => (left.id < right.id ? -1 : left.id > right.id ? 1 : 0));\n}\n"],"mappings":";AAyDA,SAAgB,sBAA+D,UAAgC;AAC3G,QAAO;;AA8FX,MAAa,kCAAkC;AA+E/C,MAAM,oCAAoC;AAC1C,MAAM,uCAAuC;AAC7C,MAAM,oCAAoC;AAE1C,SAAgB,4BAAmD;AAC/D,QAAO;EACH,MAAM;EACN,aAAa;GACT;GACA;GACA;GACH,CAAC,KAAK,IAAI;EACX,aAAa,iCAAiC,wCAAwC;EACzF;;AAGL,SAAgB,iCAAwD;AACpE,QAAO;EACH,MAAM;EACN,aAAa;GACT;GACA;GACA;GACH,CAAC,KAAK,IAAI;EACX,aAAa,iCAAiC,wCAAwC;EACzF;;AAGL,SAAgB,wBACZ,UACA,aACA,UAA4C,EAAE,EACf;CAC/B,MAAMA,SAA2C,EAAE;CACnD,MAAM,iBAAiB,IAAI,IAAI,YAAY,KAAI,SAAQ,KAAK,KAAK,CAAC;AAElE,KAAI,CAAC,SAAS,SAAS,CACnB,QAAO;EACH,OAAO;EACP,QAAQ,CACJ;GACI,MAAM;GACN,SAAS;GACT,MAAM;GACT,CACJ;EACJ;AAGL,KAAI,cAAc,SACd,QAAO,KAAK;EACR,MAAM;EACN,SAAS;EACT,MAAM;EACT,CAAC;AAGN,KAAI,CAAC,SAAS,SAAS,SAAS,CAC5B,QAAO,KAAK;EACR,MAAM;EACN,SAAS;EACT,MAAM;EACT,CAAC;UACK,QAAQ,aAAa,UAAa,SAAS,aAAa,QAAQ,SACvE,QAAO,KAAK;EACR,MAAM;EACN,SAAS,6BAA6B,SAAS,SAAS,kCAAkC,QAAQ,SAAS;EAC3G,MAAM;EACT,CAAC;CAGN,MAAM,cAAc,gBAAgB,UAAU,eAAe,QAAQ,KAAK;CAC1E,MAAM,YAAY,gBAAgB,UAAU,aAAa,QAAQ,MAAM;CACvE,MAAM,eAAe,gBAAgB,UAAU,gBAAgB,QAAQ,KAAK;CAC5E,MAAM,mBAAmB,gBAAgB,UAAU,oBAAoB,QAAQ,MAAM;CACrF,MAAM,4BAA4B,IAAI,IAAI,CAAC,GAAI,QAAQ,oBAAoB,EAAE,EAAG,GAAG,iBAAiB,CAAC;AAErG,mBAAkB,aAAa,gBAAgB,QAAQ,gBAAgB;AACvE,mBAAkB,WAAW,gBAAgB,QAAQ,cAAc;AACnE,mBAAkB,cAAc,gBAAgB,QAAQ,iBAAiB;AACzE,mBAAkB,kBAAkB,gBAAgB,QAAQ,qBAAqB;AAEjF,MAAK,MAAM,YAAY,YACnB,KAAI,0BAA0B,IAAI,SAAS,CACvC,QAAO,KAAK;EACR,MAAM;EACN,SAAS,QAAQ,SAAS;EAC1B,MAAM;EACN;EACH,CAAC;AAIV,mBAAkB,SAAS,WAAW,gBAAgB,OAAO;AAC7D,uBAAsB,SAAS,eAAe,OAAO;AAErD,QAAO;EACH,OAAO,OAAO,WAAW;EACzB;EACH;;AAGL,SAAgB,yBAAyB,UAA0D;AAC/F,QAAO;EACH,UAAU,SAAS;EACnB,aAAa,aAAa,SAAS,YAAY;EAC/C,WAAW,qBAAqB,SAAS,UAAU;EACnD,cAAc,aAAa,SAAS,aAAa;EACjD,kBAAkB,qBAAqB,SAAS,iBAAiB;EACjE,WAAW,eAAe,SAAS,UAAU;EAC7C,eAAe,SAAS,eAAe,KAAI,aAAY,EAAE,GAAG,SAAS,EAAE;EACvE,WAAW,SAAS,cAAc,SAAY,SAAY,EAAE,GAAG,SAAS,WAAW;EACtF;;AAGL,SAAgB,iCAAiC,UAAyD;CACtG,MAAM,aAAa,yBAAyB,SAAS;AAErD,QAAO;EACH,eAAe;EACf,UAAU,WAAW;EACrB,aAAa,WAAW;EACxB,WAAW,WAAW;EACtB,cAAc,WAAW;EACzB,kBAAkB,WAAW;EAC7B,WAAW,WAAW;EACtB,eAAe,WAAW;EAC1B,WAAW,WAAW;EACzB;;AAGL,SAAgB,iCACZ,UACA,UACA,UAAsD,EAAE,EACzC;AACf,QAAO,mBAAmB;EACtB;EACA,gBAAgB,iCAAiC,SAAS;EAC1D,gBAAgB,QAAQ;EAC3B,CAAC;;AAGN,SAAgB,mBAAmB,OAAiD;CAChF,MAAM,WAAW,MAAM;CACvB,MAAM,iBAAiB,MAAM;CAC7B,MAAM,iBAAiB,MAAM;CAC7B,MAAM,mBAAmB,SAAS,YAAY,EAAE;CAChD,MAAM,kBAAkB,gBAAgB,YAAY,EAAE;AAEtD,oCAAmC,UAAU,gBAAgB,iBAAiB;AAC9E,oCAAmC,UAAU,eAAe;CAE5D,MAAM,mBAAmB,aAAa;EAClC,GAAI,iBAAiB,oBAAoB,EAAE;EAC3C,GAAI,gBAAgB,oBAAoB,EAAE;EAC1C,GAAI,gBAAgB,oBAAoB,EAAE;EAC7C,CAAC;CACF,MAAM,qBAAqB,IAAI,IAAI,iBAAiB;CACpD,MAAM,cAAc,aAAa;EAC7B,GAAI,iBAAiB,eAAe,EAAE;EACtC,IAAI,gBAAgB,eAAe,EAAE,EAAE,QAAO,aAAY,CAAC,mBAAmB,IAAI,SAAS,CAAC;EAC5F,IAAI,gBAAgB,eAAe,EAAE,EAAE,QAAO,aAAY,CAAC,mBAAmB,IAAI,SAAS,CAAC;EAC/F,CAAC;CACF,MAAM,YAAY,aAAa;EAC3B,GAAI,iBAAiB,aAAa,EAAE;EACpC,IAAI,gBAAgB,aAAa,EAAE,EAAE,QAAO,aAAY,CAAC,mBAAmB,IAAI,SAAS,CAAC;EAC1F,IAAI,gBAAgB,aAAa,EAAE,EAAE,QAAO,aAAY,CAAC,mBAAmB,IAAI,SAAS,CAAC;EAC7F,CAAC;CACF,MAAM,eAAe,aAAa;EAC9B,GAAI,iBAAiB,gBAAgB,EAAE;EACvC,GAAI,gBAAgB,gBAAgB,EAAE;EACtC,GAAI,gBAAgB,gBAAgB,EAAE;EACtC,GAAG;EACN,CAAC;CACF,MAAMC,YAAoD,OAAO,OAC7D,EAAE,EACF,gBAAgB,WAChB,iBAAiB,WACjB,gBAAgB,UACnB;CACD,MAAM,gBAAgB,mBAAmB,gBAAgB,eAAe,SAAS,QAAQ,UAAU,gBAAgB,QAAQ,SAAS;AAEpI,QAAO;EACH,QAAQ,EAAE,GAAG,SAAS,QAAQ;EAC9B,UAAU;GACN,GAAG;GACH,GAAG;GACH;GACA;GACA;GACA;GACA;GACH;EACD,QACI,SAAS,WAAW,UAAa,gBAAgB,WAAW,UAAa,cAAc,WAAW,IAC5F,SACA,OAAO,OAAO,EAAE,EAAE,SAAS,QAAQ,gBAAgB,QAAQ,EAAE,UAAU,eAAe,CAAC;EACpG;;AAGL,SAAgB,uBAAuB,UAA2B,aAAqD;CACnH,MAAM,kBAAkB,IAAI,IAAI,SAAS,UAAU,YAAY;CAC/D,MAAM,gBAAgB,IAAI,IAAI,SAAS,UAAU,UAAU;CAC3D,MAAM,uBAAuB,IAAI,IAAI,SAAS,UAAU,iBAAiB;CACzE,MAAM,mBAAmB,IAAI,IAAI,CAAC,GAAI,SAAS,UAAU,gBAAgB,EAAE,EAAG,GAAG,qBAAqB,CAAC;AAEvG,MAAK,MAAM,QAAQ,YACf,KAAI,CAAC,gBAAgB,IAAI,KAAK,KAAK,IAAI,CAAC,cAAc,IAAI,KAAK,KAAK,CAChE,kBAAiB,IAAI,KAAK,KAAK;AAIvC,QAAO;EACH,QAAQ,SAAS;EACjB,OAAO,YAAY,SAAS,cAAc;EAC1C;EACA;EACA;EACA;EACA,WAAW,SAAS,UAAU,aAAa,EAAE;EAC7C,aAAa,SAAS,QAAQ,YAAY,EAAE,EAAE,KAAI,aAAY;GAC1D,IAAI,QAAQ;GACZ,OAAO,QAAQ;GACf,SAAS,QAAQ;GACjB,UAAU,SAAS,OAAO;GAC7B,EAAE;EACH,QAAQ;GACJ,wBAAwB,SAAS,UAAU,0BAA0B;GACrE,2BAA2B,SAAS,UAAU,6BAA6B;GAC3E,wBAAwB,SAAS,UAAU,0BAA0B;GACxE;EACJ;;AAGL,SAAgB,aAAa,OAAsB,OAAoC;AACnF,KAAI,MAAM,aAAa,MAAM,OAAO,GAChC,OAAM,IAAI,MAAM,yBAAyB,MAAM,SAAS,+BAA+B,MAAM,OAAO,KAAK;CAG7G,MAAM,aAAa,iBAAiB,OAAO,MAAM,KAAK;CACtD,MAAM,aAAa,6BAA6B;AAEhD,KAAI,MAAM,SAAS,SACf,QAAO;EACH;EACA,cAAc,CAAC,WAAW;EAC1B,WAAW,EAAE;EACb,YAAY,EAAE;EACjB;AAGL,KAAI,MAAM,SAAS,UACf,QAAO;EACH;EACA,cAAc,CAAC,WAAW;EAC1B,WAAW,MAAM,MAAM,KAAI,SAAQ,qBAAqB,MAAM,OAAO,IAAI,MAAM,iBAAiB,MAAM,WAAW,KAAK,CAAC;EACvH,YAAY,MAAM;EACrB;CAGL,MAAM,kBAAkB,IAAI,IAAI,MAAM,YAAY;CAClD,MAAM,mBAAmB,IAAI,IAAY;EAAC,GAAG,MAAM;EAAiB,GAAG,MAAM;EAAe,GAAG;EAAgB,CAAC;AAChH,MAAK,MAAM,YAAY,MAAM,qBACzB,kBAAiB,OAAO,SAAS;AAQrC,QAAO;EACH;EACA,cAPiB,CAAC,GADK,MAAM,MAAM,QAAO,SAAQ,iBAAiB,IAAI,KAAK,KAAK,CAAC,EACzC,WAAW;EAQpD,WAPc,MAAM,MACnB,QAAO,SAAQ,CAAC,iBAAiB,IAAI,KAAK,KAAK,CAAC,CAChD,KAAI,SAAQ,qBAAqB,MAAM,OAAO,IAAI,MAAM,iBAAiB,MAAM,WAAW,KAAK,CAAC;EAMjG,YAAY,MAAM;EACrB;;AAGL,SAAgB,8BAAqD;AACjE,QAAO;EACH,MAAM;EACN,aAAa;EACb,aAAa;GACT,MAAM;GACN,YAAY;IACR,QAAQ;KACJ,MAAM;KACN,aAAa;KAChB;IACD,SAAS;KACL,MAAM;KACN,aAAa;KAChB;IACJ;GACD,UAAU,CAAC,UAAU;GACrB,sBAAsB;GACzB;EACJ;;AAGL,SAAgB,8BAA8B,MAA0C;AACpF,QAAO;EACH,OAAO,KAAK;EACZ,SAAS;GACL,YAAY,KAAK;GACjB,WAAW,KAAK;GAChB,YAAY,KAAK;GACpB;EACJ;;AAGL,SAAgB,2BAA2B,OAAsB,MAA4C;CACzG,MAAM,uBAAuB,KAAK,UAAU,MAAM,MAAM,CAAC;CACzD,MAAM,0BAA0B,KAAK,UAAU,KAAK,aAAa,CAAC;CAClE,MAAM,wBAAwB,KAAK,UAAU,KAAK,UAAU,CAAC;CAC7D,MAAM,0BAA0B,0BAA0B;AAE1D,QAAO;EACH,iBAAiB,MAAM,MAAM;EAC7B,kBAAkB,KAAK,aAAa;EACpC,kBAAkB,KAAK,UAAU;EACjC;EACA;EACA;EACA,wBAAwB,uBAAuB;EAC/C,wBAAwB,KAAK,UAAU,SAAS,IAAI,IAAI;EACxD;EACH;;AAGL,IAAa,kBAAb,MAA6B;CACzB,AAAO,YAAY,AAAiBC,OAAsB;EAAtB;;CAEpC,AAAO,KAAK,OAAoC;AAC5C,SAAO,aAAa,KAAK,OAAO,MAAM;;;AAI9C,IAAa,wBAAb,MAAmC;CAC/B;CAEA,AAAO,YACH,AAAiBA,OACjB,cACF;EAFmB;AAGjB,QAAKC,QAAS;GACV,UAAU,MAAM,OAAO;GACvB,MAAM,cAAc,QAAQ;GAC5B,aAAa,cAAc,eAAe,EAAE;GAC/C;;CAGL,AAAO,aAAmC;AACtC,SAAO,8BAA8B,aAAa,KAAK,OAAO,MAAKA,MAAO,CAAC;;CAG/E,AAAO,OAAO,SAAsC;AAChD,MAAI,QAAQ,WAAW,UAAa,QAAQ,WAAW,KAAK,MAAM,OAAO,GACrE,QAAO;GACH,UAAU,KAAK,MAAM,OAAO;GAC5B,gBAAgB,EAAE;GAClB,MAAM,MAAKA,MAAO;GACrB;EAIL,MAAM,gBADe,MAAKC,WAAY,QAAQ,CACX,QAAO,aAAY,CAAC,KAAK,MAAM,qBAAqB,IAAI,SAAS,CAAC;EACrG,MAAM,iBAAiB,cAAc,QAAO,aAAY,CAAC,KAAK,MAAM,gBAAgB,IAAI,SAAS,CAAC;AAClG,MAAI,cAAc,WAAW,KAAK,QAAQ,WAAW,OACjD,QAAO;GACH,UAAU,KAAK,MAAM,OAAO;GAC5B;GACA,MAAM,MAAKD,MAAO;GACrB;AAGL,QAAKA,QAAS;GACV,UAAU,KAAK,MAAM,OAAO;GAC5B,MAAM;GACN,aAAa,eAAe,MAAKA,MAAO,aAAa,eAAe;GACvE;AAED,SAAO;GACH,UAAU,KAAK,MAAM,OAAO;GAC5B;GACA,MAAM,MAAKA,MAAO;GACrB;;CAGL,YAAY,SAAkC;AAC1C,MAAI,QAAQ,WAAW,UAAa,QAAQ,WAAW,KAAK,MAAM,OAAO,GACrE,QAAO,EAAE;EAGb,MAAM,oBAAoB,oBAAoB,QAAQ,QAAQ;AAW9D,SAVgB,KAAK,MAAM,MACtB,QAAO,SAAQ;GACZ,MAAM,OAAO,KAAK,MAAM,UAAU,KAAK;AAIvC,UAAO,iBAAiB,mBAHP,oBACb,GAAG,KAAK,KAAK,GAAG,KAAK,YAAY,GAAG,MAAM,SAAS,GAAG,GAAG,MAAM,WAAW,GAAG,IAAI,MAAM,YAAY,EAAE,EAAE,KAAK,IAAI,GACnH,CACmD;IACtD,CACD,KAAI,SAAQ,KAAK,KAAK;;;AAMnC,SAAS,iBAAiB,OAAsB,MAAgC;AAC5E,QAAO;EACH,IAAI,MAAM,OAAO;EACjB,OAAO,MAAM,OAAO,SAAS,MAAM,OAAO;EAC1C,SAAS,MAAM,OAAO;EACtB;EACH;;AAGL,SAAS,qBACL,UACA,iBACA,WACA,MACc;CACd,MAAM,OAAO,UAAU,KAAK;AAE5B,QAAO;EACH,IAAI,KAAK;EACT,OAAO,MAAM,SAAS,KAAK;EAC3B,SAAS,MAAM,WAAW,KAAK;EAC/B,YAAY;GACR;GACA,UAAU,KAAK;GAClB;EACD,QAAQ,gBAAgB,IAAI,KAAK,KAAK;EACzC;;AAGL,SAAS,cAAc,MAA6B,OAAsC;AACtF,QAAO,KAAK,OAAO,MAAM,OAAO,KAAK,KAAK,OAAO,MAAM,OAAO,IAAI;;AAGtE,SAAS,eAAe,SAAwC,MAAmC;AAC/F,QAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAI,WAAW,EAAE,EAAG,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU;;AAGjE,SAAS,oBAAoB,OAAuB;AAChD,QAAO,MAAM,aAAa,CAAC,WAAW,qBAAqB,IAAI;;AAGnE,SAAS,iBAAiB,SAAiB,UAA2B;CAClE,MAAM,eAAe,QAAQ,MAAM,IAAI,CAAC,QAAO,SAAQ,uBAAuB,KAAK,CAAC;CACpF,MAAM,gBAAgB,SAAS,MAAM,IAAI,CAAC,QAAO,SAAQ,uBAAuB,KAAK,CAAC;AAEtF,QAAO,aAAa,MAAK,gBACrB,cAAc,MAAK,iBAAgB,YAAY,SAAS,aAAa,IAAI,aAAa,SAAS,YAAY,CAAC,CAC/G;;AAGL,SAAS,uBAAuB,MAAuB;AACnD,KAAI,SAAS,GACT,QAAO;AAGX,QAAO,CAAC,GAAG,KAAK,CAAC,MAAK,eAAc,UAAU,YAAY,EAAE,IAAI,KAAK,IAAK,IAAI,KAAK,UAAU;;AAGjG,SAAS,iCAAiC,aAAiC;AACvE,QAAO;EACH,MAAM;EACN;EACA,YAAY;GACR,UAAU;IACN,MAAM;IACN,aAAa;IAChB;GACD,aAAa;IACT,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,UAAU;IAC5B;GACD,WAAW;IACP,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,UAAU;IAC5B;GACD,cAAc;IACV,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,UAAU;IAC5B;GACD,kBAAkB;IACd,MAAM;IACN,aAAa;IACb,OAAO,EAAE,MAAM,UAAU;IAC5B;GACD,WAAW;IACP,MAAM;IACN,aAAa;IACb,sBAAsB;KAClB,MAAM;KACN,YAAY;MACR,OAAO,EAAE,MAAM,UAAU;MACzB,SAAS,EAAE,MAAM,UAAU;MAC3B,UAAU;OACN,MAAM;OACN,OAAO,EAAE,MAAM,UAAU;OAC5B;MACJ;KACD,UAAU,CAAC,UAAU;KACrB,sBAAsB;KACzB;IACJ;GACD,eAAe;IACX,MAAM;IACN,aAAa;IACb,OAAO;KACH,MAAM;KACN,YAAY;MACR,IAAI,EAAE,MAAM,UAAU;MACtB,OAAO,EAAE,MAAM,UAAU;MACzB,SAAS,EAAE,MAAM,UAAU;MAC9B;KACD,UAAU;MAAC;MAAM;MAAS;MAAU;KACpC,sBAAsB;KACzB;IACJ;GACD,WAAW;IACP,MAAM;IACN,aAAa;IACb,sBAAsB,EAAE,MAAM,UAAU;IAC3C;GACJ;EACD,UAAU;GAAC;GAAY;GAAe;GAAgB;GAAY;EAClE,sBAAsB;EACzB;;AAGL,SAAS,SAAS,OAAkD;AAChE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG/E,SAAS,SAAS,OAAiC;AAC/C,QAAO,OAAO,UAAU;;AAG5B,SAAS,gBACL,QACA,KACA,QACA,UACQ;CACR,MAAM,QAAQ,OAAO;AACrB,KAAI,UAAU,QAAW;AACrB,MAAI,SACA,QAAO,KAAK;GACR,MAAM;GACN,SAAS,GAAG,IAAI;GAChB,MAAM,KAAK;GACd,CAAC;AAEN,SAAO,EAAE;;AAGb,KAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,OAAM,SAAQ,SAAS,KAAK,CAAC,EAAE;AAC/D,SAAO,KAAK;GACR,MAAM;GACN,SAAS,GAAG,IAAI;GAChB,MAAM,KAAK;GACd,CAAC;AACF,SAAO,EAAE;;AAGb,QAAO;;AAGX,SAAS,kBACL,WACA,gBACA,QACA,MACI;AACJ,MAAK,MAAM,YAAY,UACnB,KAAI,CAAC,eAAe,IAAI,SAAS,CAC7B,QAAO,KAAK;EACR,MAAM;EACN,SAAS,yBAAyB,SAAS;EAC3C;EACA;EACH,CAAC;;AAKd,SAAS,kBAAkB,OAAgB,gBAAqC,QAAgD;AAC5H,KAAI,CAAC,SAAS,MAAM,EAAE;AAClB,SAAO,KAAK;GACR,MAAM;GACN,SAAS;GACT,MAAM;GACT,CAAC;AACF;;AAGJ,MAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,MAAM,EAAE;AAClD,MAAI,CAAC,eAAe,IAAI,SAAS,CAC7B,QAAO,KAAK;GACR,MAAM;GACN,SAAS,8CAA8C,SAAS;GAChE,MAAM,eAAe;GACrB;GACH,CAAC;AAGN,MAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE;AAC5C,UAAO,KAAK;IACR,MAAM;IACN,SAAS,aAAa,SAAS;IAC/B,MAAM,eAAe;IACrB;IACH,CAAC;AACF;;AAGJ,MAAI,KAAK,UAAU,UAAa,CAAC,SAAS,KAAK,MAAM,CACjD,QAAO,KAAK;GACR,MAAM;GACN,SAAS,aAAa,SAAS;GAC/B,MAAM,eAAe,SAAS;GAC9B;GACH,CAAC;AAGN,MAAI,KAAK,aAAa,WAAc,CAAC,MAAM,QAAQ,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,OAAM,YAAW,SAAS,QAAQ,CAAC,EACnH,QAAO,KAAK;GACR,MAAM;GACN,SAAS,aAAa,SAAS;GAC/B,MAAM,eAAe,SAAS;GAC9B;GACH,CAAC;;;AAKd,SAAS,sBAAsB,OAAgB,QAAgD;AAC3F,KAAI,UAAU,OACV;AAGJ,KAAI,CAAC,MAAM,QAAQ,MAAM,EAAE;AACvB,SAAO,KAAK;GACR,MAAM;GACN,SAAS;GACT,MAAM;GACT,CAAC;AACF;;AAGJ,MAAK,MAAM,CAAC,OAAO,YAAY,MAAM,SAAS,CAC1C,KAAI,CAAC,SAAS,QAAQ,IAAI,CAAC,SAAS,QAAQ,GAAG,IAAI,CAAC,SAAS,QAAQ,MAAM,IAAI,CAAC,SAAS,QAAQ,QAAQ,CACrG,QAAO,KAAK;EACR,MAAM;EACN,SAAS;EACT,MAAM,mBAAmB;EAC5B,CAAC;;AAKd,SAAS,aAAa,QAAqC;AACvD,QAAO,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,CAAC,UAAU;;AAG1C,SAAS,qBAAqB,QAA6D;AACvF,QAAO,WAAW,SAAY,SAAY,aAAa,OAAO;;AAGlE,SAAS,eAAe,OAAuF;AAC3G,QAAO,OAAO,YACV,OAAO,QAAQ,MAAM,CAChB,UAAU,CAAC,OAAO,CAAC,WAAY,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI,EAAG,CACzE,KAAK,CAAC,UAAU,UAAU,CACvB,UACA;EACI,GAAG;EACH,UAAU,KAAK,aAAa,SAAY,SAAY,CAAC,GAAG,KAAK,SAAS;EACzE,CACJ,CAAC,CACT;;AAGL,SAAS,mCACL,UACA,gBACA,OACI;AACJ,KAAI,mBAAmB,UAAa,eAAe,aAAa,SAAS,OAAO,GAC5E,OAAM,IAAI,MAAM,GAAG,MAAM,UAAU,eAAe,SAAS,kCAAkC,SAAS,OAAO,KAAK;;AAI1H,SAAS,mCAAmC,UAA2B,gBAAyD;AAC5H,KAAI,mBAAmB,UAAa,eAAe,aAAa,SAAS,OAAO,GAC5E,OAAM,IAAI,MAAM,yBAAyB,eAAe,SAAS,kCAAkC,SAAS,OAAO,KAAK;;AAIhI,SAAS,mBACL,iBACA,kBACA,iBACqB;CACrB,MAAM,2BAAW,IAAI,KAAkC;AAEvD,MAAK,MAAM,WAAW;EAAC,GAAI,mBAAmB,EAAE;EAAG,GAAI,oBAAoB,EAAE;EAAG,GAAI,mBAAmB,EAAE;EAAE,CACvG,UAAS,IAAI,QAAQ,IAAI,EAAE,GAAG,SAAS,CAAC;AAG5C,QAAO,CAAC,GAAG,SAAS,QAAQ,CAAC,CAAC,UAAU,MAAM,UAAW,KAAK,KAAK,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,EAAG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxis-ai/mcp-plus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "MCP+ wrapper-mode exposure and authoring layer for Model Context Protocol servers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/Praxis-Agent-Architecture/MCP-Plus#readme",
|