feat(foundry): add composable subject detail profiles
This commit is contained in:
+88
-1
@@ -303,6 +303,73 @@ const mapPresentationProfileInputSchema = {
|
||||
},
|
||||
};
|
||||
|
||||
const mapSubjectDetailProfileFieldInputSchema = {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["id", "source", "field", "label", "format"],
|
||||
properties: {
|
||||
id: { type: "string", description: "Stable field presentation id." },
|
||||
aspectId: { type: "string", description: "Provider-neutral subject aspect id; defaults to primary." },
|
||||
source: { type: "string", enum: ["fact", "attribute", "geometry", "context"] },
|
||||
field: { type: "string", description: "Exact registered fact, context, geometry or provider-neutral attribute field." },
|
||||
label: { type: "string", minLength: 1, maxLength: 100 },
|
||||
format: {
|
||||
type: "string",
|
||||
enum: ["text", "number", "timestamp", "boolean", "coordinate", "signal_state", "movement_state", "telemetry_readings"],
|
||||
},
|
||||
unit: { type: "string", minLength: 1, maxLength: 24 },
|
||||
allowedReadingIds: {
|
||||
type: "array",
|
||||
maxItems: 256,
|
||||
uniqueItems: true,
|
||||
description: "Explicit classified sensor ids. Empty means no dynamic readings are rendered.",
|
||||
items: { type: "string" },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mapSubjectDetailProfileInputSchema = {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["id", "version", "title", "semanticTypes", "defaultTabId", "tabs"],
|
||||
properties: {
|
||||
id: { type: "string", description: "Stable provider-neutral subject.detail_profile id." },
|
||||
version: { type: "string", pattern: "^\\d+\\.\\d+\\.\\d+$" },
|
||||
title: { type: "string", minLength: 1, maxLength: 120 },
|
||||
semanticTypes: { type: "array", minItems: 1, maxItems: 8, uniqueItems: true, items: { type: "string" } },
|
||||
defaultTabId: { type: "string" },
|
||||
tabs: {
|
||||
type: "array",
|
||||
minItems: 1,
|
||||
maxItems: 12,
|
||||
items: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["id", "label", "emptyMessage", "sections"],
|
||||
properties: {
|
||||
id: { type: "string" },
|
||||
label: { type: "string", minLength: 1, maxLength: 80 },
|
||||
emptyMessage: { type: "string", minLength: 1, maxLength: 240 },
|
||||
sections: {
|
||||
type: "array",
|
||||
maxItems: 12,
|
||||
items: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["id", "label", "fields"],
|
||||
properties: {
|
||||
id: { type: "string" },
|
||||
label: { type: "string", minLength: 1, maxLength: 80 },
|
||||
fields: { type: "array", maxItems: 32, items: mapSubjectDetailProfileFieldInputSchema },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mapPageSettingsPatchInputSchema = {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
@@ -551,6 +618,22 @@ const tools = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "foundry_upsert_map_subject_detail_profile",
|
||||
title: "Upsert Map subject detail profile",
|
||||
description: "Create or update a versioned provider-neutral subject detail profile. Tabs and fields are exact, fail-closed presentation declarations; provider transport and unrestricted payload rendering are forbidden.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["applicationId", "pageId", "idempotencyKey", "profile"],
|
||||
properties: {
|
||||
applicationId: { type: "string" },
|
||||
pageId: { type: "string", description: "Map Page instance id inside the application." },
|
||||
idempotencyKey: { type: "string" },
|
||||
profile: mapSubjectDetailProfileInputSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "foundry_update_map_page_settings",
|
||||
title: "Update Application Map settings",
|
||||
@@ -629,6 +712,9 @@ const tools = [
|
||||
semanticTypes: { type: "array", items: { type: "string" } },
|
||||
fieldProjection: { type: "array", items: { type: "string" } },
|
||||
presentationProfileId: { type: "string", description: "Existing page-owned provider-neutral Map presentation profile id." },
|
||||
subjectDetailProfileId: { type: "string", description: "Existing page-owned provider-neutral subject detail profile id." },
|
||||
aspectId: { type: "string", description: "Stable provider-neutral aspect id inside the selected subject composition." },
|
||||
joinToBindingId: { type: "string", description: "Primary Map binding whose stable sourceId is used to join this subject-details aspect." },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -728,6 +814,7 @@ function toolMap(operations) {
|
||||
foundry_upsert_map_pin_binding: (input, actor) => operations.upsertMapPinBinding(input, actor),
|
||||
foundry_remove_map_pin_binding: (input, actor) => operations.removeMapPinBinding(input, actor),
|
||||
foundry_upsert_map_presentation_profile: (input, actor) => operations.upsertMapPresentationProfile(input, actor),
|
||||
foundry_upsert_map_subject_detail_profile: (input, actor) => operations.upsertMapSubjectDetailProfile(input, actor),
|
||||
foundry_update_map_page_settings: (input, actor) => operations.updateMapPageSettings(input, actor),
|
||||
foundry_save_map_page_view_state: (input, actor) => operations.saveMapPageViewState(input, actor),
|
||||
foundry_upsert_map_data_product_binding: (input, actor) => operations.upsertMapDataProductBinding(input, actor),
|
||||
@@ -772,7 +859,7 @@ export async function handleFoundryMcpRequest(request, response, options) {
|
||||
return sendJson(response, 200, mcpResult(id, {
|
||||
protocolVersion: MCP_PROTOCOL_VERSION,
|
||||
capabilities: { tools: { listChanged: false } },
|
||||
serverInfo: { name: "nodedc_module_foundry", version: "0.5.0" },
|
||||
serverInfo: { name: "nodedc_module_foundry", version: "0.6.0" },
|
||||
instructions: "NDC Module Foundry edits application instances, provider-neutral map presentation profiles and approved server-owned data-product consumers. Page Library is read-only. Application deletion is unavailable. Provider endpoints and credentials are never MCP inputs or outputs.",
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user