Skip to main content

Tool Types

The @interopio/mcp-core package supports three categories of tools that LLMs can invoke to interact with io.Connect applications. Each category serves different use cases and follows specific registration and lifecycle patterns.

System Tools

Experimental

All system tools are currently experimental and may change in future releases. Use them with caution in production environments.

System tools are built-in tools provided by MCP Core for discovering and launching applications and workspaces. These tools are automatically configured based on client capabilities and io.Connect API availability.

io_connect_search_applications

Experimental

This system tool is experimental and may change in future releases.

Discovers applications that can satisfy user intent and returns their interaction schemas.

Input Schema:

{
userIntent: string; // Description of what user wants to accomplish
}

Output Schema:

{
canSatisfyUserIntent: boolean;
summary: string;
nextSteps: string;
willSatisfyUserIntentBy: {
workspace?: {
apps: ApplicationInfo[];
};
apps?: ApplicationInfo[];
};
}

Requires:

  • Client sampling capability

Configuration:

system: {
searchApps: {
enabled: true,
overrides: {
name: "custom_search_apps",
description: "Custom description"
},
guard: (app) => app.name !== "internal-app"
}
}

The guard function filters which applications are included in search results. Applications without a caption property are automatically filtered out.

io_connect_search_workspaces

Experimental

This system tool is experimental and may change in future releases.

Discovers saved workspaces that satisfy user intent.

Input Schema:

{
userIntent: string;
}

Output Schema:

{
canSatisfyUserIntent: boolean;
summary: string;
nextSteps: string;
willSatisfyUserIntentBy: {
workspace?: {
name: string;
description: string;
contextSchema: object;
};
};
}

Requires:

  • Client sampling capability
  • io.Connect Workspaces API available

Configuration:

system: {
searchWorkspaces: {
enabled: true,
overrides: {
name: "custom_search_workspaces"
},
guard: (ws) => !ws.name.startsWith("_internal")
}
}

Workspaces without a metadata.description property are automatically excluded from search results.

io_connect_start_applications

Experimental

This system tool is experimental and may change in future releases.

Launches applications with populated context data.

Input Schema:

{
apps: Array<{
name: string;
initialInstanceContext?: object;
startOptions?: {
channelName?: string;
height?: number;
width?: number;
top?: number;
left?: number;
};
interop?: {
method?: {
name: string;
params?: object;
};
windowContext?: object;
intent?: {
name: string;
intentContextType?: string;
intentContextData?: object;
};
};
}>;
}

Output Schema:

{
apps: Array<{
name: string;
status: "success" | "error";
responseData?: any;
errorMessage?: string;
}>;
}

Requires:

  • Client elicitation capability

Configuration:

system: {
startApps: {
enabled: true,
overrides: {
description: "Custom start description"
}
}
}

io_connect_start_workspace

Experimental

This system tool is experimental and may change in future releases.

Creates new workspace or restores existing workspace with context.

Input Schema:

{
workspace:
| { name: string; context?: object } // Restore existing workspace
| { apps: Array<...>; workspaceContext?: object } // Create new workspace
}

Output Schema:

{
result: {
id: string;
status: "success" | "error";
errorMessage?: string;
methodInvocationResults?: Array<{
app: string;
invocationResult: any;
}>;
};
}

Requires:

  • Client elicitation capability
  • io.Connect Workspaces API available

io_connect_get_workspace_widget

Experimental

This system tool is experimental and may change in future releases.

Returns a workspace widget payload that opens an interactive MCP App in the host application. The widget provides a visual, interactive surface for two workspace-related workflows:

  • Previewer mode — renders an existing workspace layout in a read-only view before the user decides to open it
  • Builder mode — provides a drag-and-drop canvas for creating a new workspace layout from scratch, starting from an AI-suggested component structure or an empty canvas

This tool is an MCP App — when invoked, the host application renders a live HTML panel (inline or as a workspace window) rather than returning plain text. The client must advertise MCP App UI support for the tool to be registered.

For a complete user-facing explanation of both modes, the interaction workflow, state persistence behavior, and the full custom notification reference, see Workspace Widget.


Input Schema:

{
mode?: "previewer" | "builder"; // default: "previewer"
workspaceName?: string | null; // name of an existing workspace to fetch (previewer)
components?: string | null; // workspace component tree as JSON string (builder or previewer with custom layout)
}

Input Parameter Details:

ParameterTypeDescription
mode"previewer" | "builder"Selects between read-only preview and interactive builder. Defaults to "previewer".
workspaceNamestring | nullWhen provided, the tool fetches this workspace's layout from io.Connect. Takes priority over components. Use in previewer mode to show an existing workspace.
componentsstring | nullA complete workspace component tree serialized as a JSON string. Used when workspaceName is not provided. In builder mode, this pre-populates the canvas. In previewer mode, renders a custom layout rather than a named workspace.

Component tree structure (for components):

{
children: Array<
| { type: "window"; appName: string }
| { type: "group"; children: WindowNode[]; config?: { activeTabIndex?: number } }
| { type: "row"; children: LayoutNode[]; config?: { height?: number } }
| { type: "column"; children: LayoutNode[]; config?: { width?: number } }
>;
context?: object | null;
config?: { title?: string; [key: string]: any } | null;
frame?: object | null;
}

Component tree examples:

// Side-by-side apps
{"children":[{"type":"row","children":[{"type":"window","appName":"app1"},{"type":"window","appName":"app2"}]}],"config":{"title":"Side by Side"}}

// Tabbed apps
{"children":[{"type":"group","children":[{"type":"window","appName":"app1"},{"type":"window","appName":"app2"}],"config":{"activeTabIndex":0}}],"config":{"title":"Tabbed"}}

// Complex nested: two rows stacked vertically
{"children":[{"type":"column","children":[{"type":"row","children":[{"type":"window","appName":"app1"},{"type":"window","appName":"app2"}],"config":{"height":60}},{"type":"group","children":[{"type":"window","appName":"app3"}],"config":{"height":40}}]}],"config":{"title":"Dashboard"}}

Output Schema:

{
mode: string;
workspaceName: string | null;
components: {
children: object[];
context?: object | null;
config?: object | null;
frame?: object | null;
} | null;
success: boolean;
error: string;
}

Requires:

  • Client UI extension capability through capabilities.extensions["io.modelcontextprotocol/ui"] with mimeTypes: ["text/html;profile=mcp-app"]
  • io.Connect Workspaces API available

Configuration:

system: {
getWorkspaceWidget: {
enabled: true,
overrides: {
name: "custom_workspace_widget",
description: "Return a workspace widget payload for preview or builder flows",
},
},
}

MCP Apps Custom Notifications:

The Workspace Widget uses all five io.Intelligence custom notifications:

DirectionMethodPurpose
Host → Widgetui/notifications/response-generation-statusLock/unlock controls while AI is generating
Host → Widgetui/notifications/load-stateRestore saved canvas state after thread switch
Host → Widgetui/notifications/save-state-responseAcknowledge a state write
Widget → Hostui/notifications/save-stateCheckpoint current canvas layout
Widget → Hostui/notifications/close-ws-appSignal job done after workspace is created

Host applications that do not implement these notifications will still display the widget, but users lose response-lock feedback, canvas state persistence, and automatic close-on-complete behavior.

io_connect_get_working_context

Experimental

This system tool is experimental and may change in future releases.

Retrieves current working context from io.Connect.

Input: None

Output Schema:

{
workingContext: Record<
string,
{
description?: string;
value: any;
}
>;
}

Requires:

  • Working context configured in MCP Core configuration
  • Client does not declare experimental.workingContext

Static Tools

Static tools are defined in configuration and automatically managed by MCP Core. They are registered as MCP tools and invoke io.Connect interop methods or intents when called by LLMs.

Static Method Tools

Static method tools map MCP tool invocations to io.Connect interop methods.

Configuration Example:

static: {
methods: [
{
availability: "constant", // or "variable"
name: "my-tool-hello",
config: {
description: "Greets a person",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "Person's name"
}
},
required: ["name"]
},
outputSchema: {
type: "object",
properties: {
greeting: {
type: "string"
}
},
required: ["greeting"]
}
},
interop: {
methodName: "my_custom_method",
responseTimeoutMs: 5000,
allowedApplications: ["app1", "app2"]
}
}
]
}

Availability Modes

Constant:

  • Registered at startup
  • Never unregistered during server lifecycle
  • Use when the underlying interop method is always available

Variable:

  • Registered and unregistered automatically based on interop method availability
  • MCP Core monitors method availability changes
  • Use when methods may appear or disappear during runtime

Interop Application

The application must register the corresponding interop method:

await io.interop.register(
{
name: "my_custom_method"
},
(args) => {
return { greeting: `Hello, ${args.name}` };
}
);

Static Intent Tools

Static intent tools map MCP tool invocations to io.Connect intents.

Configuration Example:

static: {
intents: [
{
availability: "variable",
name: "my-intent-tool",
config: {
description: "Handles custom intent",
inputSchema: {
type: "object",
properties: {
type: {
type: "string"
},
data: {
type: "object"
}
},
required: ["type"]
},
outputSchema: {
type: "object",
properties: {
result: {
type: "string"
}
}
}
},
interop: {
intentName: "my_custom_intent",
resolutionStrategy: "mcp", // or "io_connect"
allowedApplications: ["handler-app"]
}
}
]
}

Resolution Strategies

mcp:

  • Prefers application-level intent handlers over instance handlers
  • Provides more predictable behavior for LLM interactions
  • Recommended for most use cases

io_connect:

  • Uses io.Connect's default intent resolution logic
  • May present multiple handler choices to the user
  • Use when standard io.Connect behavior is required

Interop Application

The application must register the corresponding intent handler:

await io.intents.register(
{
intent: "my_custom_intent"
},
(ctx) => {
return { result: `Processed ${ctx.data.type}` };
}
);

Dynamic Tools

Dynamic tools are registered at runtime by applications using io.Connect's interop API with MCP-specific flags. These tools are entirely managed by the application and automatically appear or disappear as MCP tools based on interop method registration.

Registration Example

await io.interop.register(
{
name: "awesome-method",
description: "An awesome MCP tool", // Required
flags: {
ioIntelMCPTool: {
name: "io_greeting_tool",
inputSchema: JSON.stringify({
$schema: "https://json-schema.org/draft-07/schema",
type: "object",
properties: {
name: {
type: "string",
description: "Person's name"
}
},
required: ["name"]
}),
outputSchema: JSON.stringify({
type: "object",
properties: {
greeting: {
type: "string"
}
},
required: ["greeting"]
})
}
}
},
(args) => {
return { greeting: `Hello, ${args.name}` };
}
);

InteropMethodToolConfig Interface

interface InteropMethodToolConfig {
name: string;
inputSchema: string; // JSON Schema as string
outputSchema: string; // JSON Schema as string
title?: string;
annotations?: {
title?: string;
readOnlyHint?: boolean;
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
};
_meta?: Record<string, unknown>;
responseTimeoutMs?: number;
}

Properties:

PropertyTypeRequiredDescription
namestringYesMCP tool name
inputSchemastringYesJSON Schema defining input parameters (as JSON string)
outputSchemastringYesJSON Schema defining output structure (as JSON string)
titlestringNoHuman-readable tool title
annotationsobjectNoTool behavior hints for LLM
_metaRecord<string, unknown>NoCustom metadata
responseTimeoutMsnumberNoTimeout for method invocation

Guard Function Configuration

Filter which interop methods become MCP tools using a guard function:

dynamic: {
methods: {
enabled: true,
guard: (method, server) => {
return method.name.startsWith("mcp_") &&
server.applicationName === "allowed-app";
}
}
}

Guard Function Parameters:

  • method: The interop method definition including name, description, and flags
  • server: Server information including applicationName

Returns: boolean - true to register the method as an MCP tool, false to exclude it

Application and Workspace Definition Requirements

For system search tools to function effectively, applications and workspaces must include specific properties in their definitions.

Application Definition Requirements

Required Properties:

  • caption: A clear, descriptive explanation of what the application does. Applications without this property cannot be explained to the LLM and will be filtered out from search results.

Optional Properties:

  • customProperties.interop: Detailed information about interoperability features following the ApplicationInteropInfo interface:
    • methods: Array of interop methods the application exposes
    • context: Context data requirements and sources
    • intents: Intents the application can handle

Example Application Definition:

{
"name": "proposal",
"type": "window",
"caption": "Manages and displays client proposals with detailed financial information",
"details": {
"url": "http://localhost:4100?intent=my_custom_intent"
},
"customProperties": {
"includeInWorkspaces": true,
"interop": {
"methods": [
{
"name": "get-proposal-data",
"description": "Get proposal data from the proposal app",
"inputSchema": {
"type": "object",
"properties": {
"proposalId": {
"type": "string",
"description": "The ID of the proposal to retrieve"
}
},
"required": ["proposalId"]
},
"outputSchema": {
"type": "object",
"properties": {
"proposalId": { "type": "string" },
"clientName": { "type": "string" },
"amount": { "type": "number" },
"status": { "type": "string" }
},
"required": ["proposalId", "clientName", "amount", "status"]
}
}
],
"context": {
"sources": [
"initial-instance",
"global",
"channel",
"window",
"workspace"
],
"description": "The app uses the context data to identify the proposal to display.",
"schema": {
"type": "object",
"properties": {
"proposalId": {
"type": "string",
"description": "The ID of the proposal"
},
"clientName": {
"type": "string",
"description": "The name of the client"
}
},
"required": ["proposalId", "clientName"]
}
},
"intents": [
{
"name": "my_custom_intent",
"description": "Handles requests to view proposal details.",
"contextTypes": ["fdc3.proposal"],
"inputSchema": {
"type": "object",
"properties": {
"proposalId": { "type": "string" },
"clientName": { "type": "string" }
},
"required": ["proposalId", "clientName"]
},
"outputSchema": {
"type": "object",
"properties": {
"status": { "type": "string" }
},
"required": ["status"]
},
"resultType": "fdc3.intentResult",
"displayName": "View Proposal Details"
}
]
}
},
"intents": [
{
"name": "my_custom_intent"
}
]
}

Workspace Definition Requirements

Required Properties:

  • metadata.description: A clear explanation of what the workspace layout contains and its purpose. Workspaces without this property will be excluded from search results.

Optional Properties:

  • metadata.contextSchema: JSON Schema defining the shape of the context object the workspace uses. Describes expected structure and properties of workspace context data.

Example Workspace Definition:

{
"name": "All Demos",
"type": "Workspace",
"metadata": {
"description": "A workspace layout containing all demo applications for comprehensive product demonstration.",
"contextSchema": {
"type": "object",
"properties": {
"clientId": {
"type": "string",
"description": "The client identifier to load across all applications"
},
"portfolioId": {
"type": "string",
"description": "The portfolio identifier to display"
}
},
"required": ["clientId"]
}
},
"components": []
}

Impact on System Tools

Applications and workspaces that do not meet the required property specifications are automatically filtered out during search operations:

  • Applications without caption: Cannot be analyzed by the LLM and will not appear in search results
  • Applications with only global/channel context sources: Filtered out as they lack specific interop capabilities
  • Workspaces without metadata.description: Cannot be explained to the LLM and will be excluded from workspace searches

Providing optional properties like customProperties.interop for applications and metadata.contextSchema for workspaces enhances the LLM's ability to make informed decisions about which applications or workspaces best satisfy user intent.