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
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
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
samplingcapability
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
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
samplingcapability - 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
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
elicitationcapability
Configuration:
system: {
startApps: {
enabled: true,
overrides: {
description: "Custom start description"
}
}
}
io_connect_start_workspace
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
elicitationcapability - io.Connect Workspaces API available
io_connect_get_workspace_widget
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:
| Parameter | Type | Description |
|---|---|---|
mode | "previewer" | "builder" | Selects between read-only preview and interactive builder. Defaults to "previewer". |
workspaceName | string | null | When provided, the tool fetches this workspace's layout from io.Connect. Takes priority over components. Use in previewer mode to show an existing workspace. |
components | string | null | A 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"]withmimeTypes: ["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:
| Direction | Method | Purpose |
|---|---|---|
| Host → Widget | ui/notifications/response-generation-status | Lock/unlock controls while AI is generating |
| Host → Widget | ui/notifications/load-state | Restore saved canvas state after thread switch |
| Host → Widget | ui/notifications/save-state-response | Acknowledge a state write |
| Widget → Host | ui/notifications/save-state | Checkpoint current canvas layout |
| Widget → Host | ui/notifications/close-ws-app | Signal 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
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:
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | MCP tool name |
inputSchema | string | Yes | JSON Schema defining input parameters (as JSON string) |
outputSchema | string | Yes | JSON Schema defining output structure (as JSON string) |
title | string | No | Human-readable tool title |
annotations | object | No | Tool behavior hints for LLM |
_meta | Record<string, unknown> | No | Custom metadata |
responseTimeoutMs | number | No | Timeout 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 flagsserver: Server information includingapplicationName
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 theApplicationInteropInfointerface:methods: Array of interop methods the application exposescontext: Context data requirements and sourcesintents: 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.