Custom MCP Server
Registering an external or internally hosted MCP server — providing the IMCPServerDefinition, endpoint URL, transport type, credential reference, and DI registration.
What Makes a Valid Custom Server
Any HTTP, SSE, or StdIo process that implements the Model Context Protocol specification (tools/list + tools/call endpoints) can be registered as a custom MCP server. The server must expose a tools/list endpoint so the registry can discover its tool catalog.
Registering via API
POST /api/mcp/servers
{
"serverId": "acme-underwriting-ai",
"displayName": "Acme Underwriting AI Server",
"transportType": "Http",
"endpointUrl": "https://underwriting.acme-internal.com/mcp",
"credentialId": 301,
"timeoutSeconds": 45
}
Registering in Code (DI)
// In your server registration module (e.g., Startup.cs / Program.cs):
services.AddMCPServer(options =>
{
options.ServerId = "acme-underwriting-ai";
options.DisplayName = "Acme Underwriting AI Server";
options.TransportType = MCPTransportType.Http;
options.EndpointUrl = "https://underwriting.acme-internal.com/mcp";
options.CredentialId = 301; // resolved via ICredentialResolver at call time
options.TimeoutSeconds = 45;
});
IMCPServerDefinition — Custom Implementation
For advanced scenarios where server metadata is sourced from a database or configuration service, implement IMCPServerDefinition directly:
public class DatabaseBackedMCPServerDefinition : IMCPServerDefinition
{
public string ServerId { get; init; } = default!;
public string DisplayName { get; init; } = default!;
public MCPTransportType TransportType { get; init; }
public string EndpointUrl { get; init; } = default!;
public int CredentialId { get; init; }
public int TimeoutSeconds { get; init; }
}
// Registration from database at startup:
public class MCPServerLoader : IHostedService
{
private readonly IMCPServerRegistry _registry;
private readonly IServerConfigRepository _config;
public async Task StartAsync(CancellationToken ct)
{
var servers = await _config.GetAllActiveServersAsync(ct);
foreach (var s in servers)
_registry.Register(new DatabaseBackedMCPServerDefinition
{
ServerId = s.ServerId,
DisplayName = s.DisplayName,
TransportType = Enum.Parse<MCPTransportType>(s.TransportType),
EndpointUrl = s.EndpointUrl,
CredentialId = s.CredentialId,
TimeoutSeconds = s.TimeoutSeconds
});
}
public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
}
StdIo Server Registration
{
"serverId": "local-nlp-server",
"displayName": "Local NLP Processor",
"transportType": "StdIo",
"endpointUrl": "/opt/bfai/nlp-server/run.sh",
"credentialId": 0,
"timeoutSeconds": 30
}
For StdIo servers, endpointUrl is the path to the executable. The engine launches it as a child process, communicates via stdin/stdout using the MCP JSON-RPC protocol, and terminates the process when the tool call completes.
GET /api/mcp/servers/{serverId}/health to verify reachability and confirm the tool catalog loads correctly. A toolCount: 0 response indicates the server is reachable but tools/list returned no tools — check the server implementation.
allowedTenantIds in the registration payload. Workflow nodes in other tenants will receive a "server not found" error at runtime.