Skip to main content

MCP Integration

Endpoints for normalizing Model Context Protocol configuration, discovering the registered toolkit drivers and add-menu templates, and discovering tools from a remote MCP server.

The config-parsing, driver-listing, and template-listing routes need only an authenticated user. They are not AI-gated and carry no permission check. Tool discovery is the exception: it is AI-gated and requires write access to the toolkit's owner.

POST /api/toolkit-parse-config

Parse and normalize an MCP configuration into the shape Informer stores on a Toolkit.

Authentication: Required

Request Body:

FieldTypeRequiredDescription
configstringYesThe MCP configuration as a JSON string. The handler JSON.parses it server-side.

config is a JSON string, not an object. The handler parses it and matches one of five accepted shapes: a VS Code servers map, a Claude Desktop / Cursor mcpServers map, a direct stdio entry ({ command }), a direct remote entry ({ url } or { type, url }), or a single wrapped entry. It returns the normalized { name, slug, type, config } for the first entry it finds.

A stdio entry normalizes to type: "mcp-stdio" with config { command, defaultArgs, env } (note defaultArgs, not args). A remote entry normalizes to type: "mcp-remote" with config { serverUrl, transportType } and optional headers (note serverUrl/transportType, not url/transport). A type of http maps to transportType: "streamable-http"; sse maps to sse.

Example Request (Claude Desktop format):

{
"config": "{\"mcpServers\":{\"filesystem\":{\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-filesystem\",\"/workspace\"],\"env\":{\"LOG_LEVEL\":\"info\"}}}}"
}

Response:

Responds 200 with the normalized { name, slug, type, config } and a HAL _links.self. The incoming args become defaultArgs on the normalized stdio config; name is prettified from the entry key and slug is derived from it.

Parse an MCP config (Claude Desktop format)POST /api/toolkit-parse-config
POST /api/toolkit-parse-config. Payload is { config } where `config` is a REQUIRED JSON *string* (not an object). The handler accepts the Claude Desktop/Cursor `mcpServers` shape and normalizes the first entry to { name, slug, type, config }. A remote entry (has `url`) becomes type `mcp-remote` with config { serverUrl, transportType }; a stdio entry (has `command`) becomes `mcp-stdio` with config { command, defaultArgs, env }. Auth only, no permission, no AI gate. Returns 200.
Request body
{
"config": "{\"mcpServers\":{\"filesystem\":{\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-filesystem\",\"/workspace\"],\"env\":{\"LOG_LEVEL\":\"info\"}}}}"
}
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-parse-config"
}
},
"name": "Filesystem",
"slug": "filesystem",
"type": "mcp-stdio",
"config": {
"command": "npx",
"defaultArgs": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/workspace"
],
"env": {
"LOG_LEVEL": "info"
}
}
}
Captured from the API examples test suite; ids and timestamps are normalized.

Example Request (remote server URL):

{
"config": "{\"url\":\"https://mcp.example.com/sse\",\"type\":\"sse\",\"headers\":{\"Authorization\":\"Bearer example-token\"}}"
}

Response:

The direct remote shape normalizes to type: "mcp-remote", with the incoming url surfaced as serverUrl and type surfaced as transportType. Optional headers pass through unchanged.

Parse an MCP config (remote server URL)POST /api/toolkit-parse-config
A direct `{ url }` (or `{ type: "http" | "sse", url }`) config normalizes to type `mcp-remote`. The output config uses `serverUrl` and `transportType` (`sse`, `streamable-http`), NOT `url`/`transport`. Optional `headers` are passed through. `type: "http"` maps to transportType `streamable-http`.
Request body
{
"config": "{\"url\":\"https://mcp.example.com/sse\",\"type\":\"sse\",\"headers\":{\"Authorization\":\"Bearer example-token\"}}"
}
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-parse-config"
}
},
"name": "",
"slug": "",
"type": "mcp-remote",
"config": {
"serverUrl": "https://mcp.example.com/sse",
"transportType": "sse",
"headers": {
"Authorization": "Bearer example-token"
}
}
}
Captured from the API examples test suite; ids and timestamps are normalized.
Send JSON, not a shell command

Because config is JSON.parsed server-side, a bare command line such as npx -y @modelcontextprotocol/server-filesystem /workspace is not valid JSON and answers 400 ("Invalid JSON: ..."). Well-formed JSON that matches none of the five accepted shapes also answers 400 ("Could not parse config...").

Parse an MCP config (invalid JSON)POST /api/toolkit-parse-config
Because `config` is JSON.parsed server-side, a non-JSON string (e.g. the bare command line "npx -y @modelcontextprotocol/server-filesystem /workspace") fails with 400 "Invalid JSON: ...". Well-formed JSON that matches none of the five accepted shapes 400s with "Could not parse config...". Send a JSON string, not a shell command.
Request body
{
"config": "npx -y @modelcontextprotocol/server-filesystem /workspace"
}
Response · 400
{
"statusCode": 400,
"error": "Bad Request",
"message": "Invalid JSON: Unexpected token 'p', \"npx -y @mod\"... is not valid JSON"
}
Captured from the API examples test suite; ids and timestamps are normalized.

GET /api/toolkit-drivers

List the registered toolkit driver types as a HAL collection.

Authentication: Required

Response:

A HAL collection under _embedded["inf:toolkit-driver"]. Each row is the full driver descriptor, not just an id, name, and description.

FieldTypeDescription
idstringDriver id (mcp-stdio, mcp-remote, custom, informer, plus any from loaded bundles)
namestringDisplay name
descriptionstringDriver description
iconstringIcon name
imagestringIcon image path
viewComponentstringClient view component name
executionLocationstringclient for mcp-stdio, server for the others
allowUserInstancesbooleanWhether end users may create their own instances
canManageToolsbooleanWhether tools can be managed on the toolkit
supportsIntegrationbooleanWhether the driver can authenticate via an Integration
configSchemaobjectJSON Schema for the toolkit-level config (when applicable)
instanceConfigSchemaobjectJSON Schema for per-instance config (mcp-stdio only)

The custom driver is named "Integration Toolkit" and the informer driver is named "Informer API". Loaded bundles (for example, Ellucian ethos and experience-tasks) contribute additional driver rows.

List toolkit driver typesGET /api/toolkit-drivers
GET /api/toolkit-drivers is a HAL collection. The handler returns { items: [...] } and HAL embeds each as `inf:toolkit-driver`. Each row carries the full driver descriptor (id, name, description, icon, image, viewComponent, executionLocation, allowUserInstances, canManageTools, supportsIntegration, configSchema, instanceConfigSchema), not just { id, name, description }. `executionLocation` is "client" for mcp-stdio and "server" for the others. Auth only, no AI gate.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-drivers"
}
},
"_embedded": {
"inf:toolkit-driver": [
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-drivers/mcp-stdio"
}
},
"id": "mcp-stdio",
"name": "MCP Stdio",
"description": "Local MCP server via stdio. Runs on the client (Informer Go) and allows users to create their own instances.",
"icon": "terminal",
"image": "/images/icons/toolkit-client.svg",
"viewComponent": "mcpStdioToolkitView",
"executionLocation": "client",
"allowUserInstances": true,
"canManageTools": false,
"supportsIntegration": false,
"configSchema": "… configSchema (3 fields) omitted from docs",
"instanceConfigSchema": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
},
"description": "Additional arguments for this instance"
},
"env": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Environment variables to set"
},
"workingDirectory": {
"type": "string",
"description": "Working directory for the process"
}
}
}
},
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-drivers/mcp-remote"
}
},
"id": "mcp-remote",
"name": "MCP Remote",
"description": "Remote MCP server via SSE or HTTP. Runs on the server and can use integrations for authentication.",
"icon": "cloud",
"image": "/images/icons/toolkit-cloud.svg",
"viewComponent": "mcpRemoteToolkitView",
"executionLocation": "server",
"allowUserInstances": false,
"canManageTools": false,
"supportsIntegration": false,
"configSchema": "… configSchema (3 fields) omitted from docs"
},
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-drivers/custom"
}
},
"id": "custom",
"name": "Integration Toolkit",
"description": "Create API tools that call external services via an Integration",
"icon": "build",
"image": "/images/icons/toolkit-server.svg",
"viewComponent": "customToolkitView",
"executionLocation": "server",
"allowUserInstances": true,
"canManageTools": true,
"supportsIntegration": true
},
"… 3 more items (6 total) — omitted from docs"
]
}
}
Captured from the API examples test suite; ids and timestamps are normalized.

GET /api/toolkit-templates

List the toolkit add-menu templates as a detective-discovery collection.

Authentication: Required

Response:

A detective-discovery collection (server.dm("toolkit-builder")) under items, with a HAL _links.self and start / count / total. Each entry is { detective, id, value }, where value is the add-menu descriptor.

FieldTypeDescription
value.idstringTemplate id (mcp, custom, informer, ...)
value.groupstringAdd-menu group (e.g. __top)
value.priorityintegerSort priority within the group
value.namestringDisplay name
value.descriptionstringDisplay description
value.iconstringIcon class (e.g. fas fa-plug)
value.typestringToolkit type this template creates

The built-in detectives are mcp, custom, and informer. Loaded bundles add more entries.

List toolkit templatesGET /api/toolkit-templates
GET /api/toolkit-templates is a detective-discovery collection (server.dm("toolkit-builder")). Each entry is { detective, id, value } where `value` is the add-menu descriptor { id, group, priority, name, description, icon, type }. Built-in detectives are mcp, custom, and informer; loaded bundles (e.g. Ellucian ethos/experience_tasks) add more. Auth only, no AI gate.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/toolkit-templates"
}
},
"items": [
{
"detective": "00000000-0000-4000-8000-000000000001",
"id": "00000000-0000-4000-8000-000000000001:0",
"value": {
"id": "mcp",
"group": "__top",
"priority": 100,
"name": "MCP Server",
"description": "Connect to a Model Context Protocol (MCP) server by pasting its configuration.",
"icon": "fas fa-plug",
"type": "mcp"
}
},
{
"detective": "00000000-0000-4000-8000-000000000002",
"id": "00000000-0000-4000-8000-000000000002:0",
"value": {
"id": "custom",
"group": "__top",
"priority": 50,
"name": "Integration Toolkit",
"description": "Create an Integration Toolkit with API request Tools that you define.",
"icon": "fas fa-code",
"type": "custom"
}
},
{
"detective": "00000000-0000-4000-8000-000000000003",
"id": "00000000-0000-4000-8000-000000000003:0",
"value": {
"id": "informer",
"group": "__top",
"priority": 40,
"name": "Informer API Toolkit",
"description": "Create Tools that call Informer's internal API, authenticated as the current user.",
"icon": "fas fa-database",
"type": "informer"
}
}
],
"start": 0,
"count": 3,
"total": 3
}
Captured from the API examples test suite; ids and timestamps are normalized.

POST /api/toolkits/{id}/discover

Discover tools from a remote MCP server and save them to the Toolkit.

Authentication: Required

Pre-blocks:

  1. toolkit.lookup(params.id), which calls server.methods.ai.verify(), so the route is AI-gated.
  2. permission.toolkit.write

Path Parameters:

ParameterTypeDescription
idstringToolkit id (an mcp-remote toolkit)

The handler delegates to the toolkit driver's discover(). For mcp-remote this opens a live network connection to the configured remote MCP server and queries its tool list. Discovery for mcp-stdio toolkits happens client-side in Informer GO, not through this route.

Response:

The discovered tools, saved to the toolkit. Because discovery opens a live, non-deterministic network connection to an external MCP server, this route is not captured here.

Server-side discovery only

This endpoint performs server-side discovery for mcp-remote toolkits. mcp-stdio toolkits are discovered client-side in Informer GO and do not use this route.