MCP Server Support for FabrCore Agents

Eric Brasher February 21, 2026 at 7:35 AM 9 min read

FabrCore now supports connecting MCP (Model Context Protocol) servers to agents, giving them access to external tools — GitHub, filesystem, databases, and more — with zero agent code changes.

What is MCP?

The Model Context Protocol is an open standard for connecting AI models to external tools and data sources. Instead of writing custom integration code for every service your agent needs to talk to, MCP provides a universal protocol that lets any compliant server expose tools that any compliant client can use.

Think of it like USB for AI tools — one standard interface, endless peripherals. FabrCore is now an MCP client, which means your agents can connect to any MCP server and immediately gain access to its tools.

Option 1: Config-Driven (Zero Code)

The simplest way to connect MCP servers is through your agent configuration JSON. Add an McpServers array and you're done:

fabrcore.json
{
    "Handle": "coding-agent",
    "AgentType": "CodingAgent",
    "Models": "OpenAIProd",
    "McpServers": [
        {
            "Name": "GitHub",
            "TransportType": "Stdio",
            "Command": "npx",
            "Arguments": ["-y", "@modelcontextprotocol/server-github"],
            "Env": { "GITHUB_TOKEN": "ghp_xxx" }
        }
    ]
}

No agent code changes needed — ResolveConfiguredToolsAsync() automatically connects MCP servers and includes their tools alongside plugin and standalone tools. If an MCP server fails to connect, a warning is logged and the agent continues with its other tools.

Option 2: Code-Driven (Manual Control)

For dynamic connections at runtime, call ConnectMcpServerAsync() directly in your agent proxy:

CodingAgentProxy.cs
public override async Task OnInitialize()
{
    var mcpTools = await ConnectMcpServerAsync(new McpServerConfig
    {
        Name = "GitHub",
        Command = "npx",
        Arguments = ["-y", "@modelcontextprotocol/server-github"],
        Env = new() { ["GITHUB_TOKEN"] = Environment.GetEnvironmentVariable("GITHUB_TOKEN")! }
    });

    // Combine with other tools
    var tools = await ResolveConfiguredToolsAsync();
    tools.AddRange(mcpTools);

    // Pass to CreateChatClientAgent as usual
    _agent = await CreateChatClientAgent(config.Models!, config.Handle!, tools);
}

In code-driven mode, exceptions propagate to your code — you decide how to handle failures.

Two Transport Types

FabrCore supports both MCP transport protocols:

Stdio — launches a local process and communicates over stdin/stdout. Ideal for CLI-based MCP servers like the GitHub, filesystem, or database servers:

Stdio Example
{
    "Name": "GitHub",
    "TransportType": "Stdio",
    "Command": "npx",
    "Arguments": ["-y", "@modelcontextprotocol/server-github"],
    "Env": { "GITHUB_TOKEN": "ghp_xxx" }
}

Http — connects to a remote MCP server over HTTP. Use this for shared or hosted MCP services:

Http Example
{
    "Name": "MyRemoteTools",
    "TransportType": "Http",
    "Url": "https://mcp.example.com/sse",
    "Headers": { "Authorization": "Bearer sk-xxx" }
}

What an MCP Server Is Actually Granted

The config above is four lines, which makes it easy to miss what it does. TransportType: "Stdio" means FabrCore launches npx as a child process on the silo, hands it a GitHub token through the environment, and lets the model call whatever tools that process advertises. That is a lot of authority to grant in four lines, and it is worth granting deliberately.

Scope the credential, not the server. The token in Env is the only thing standing between a confused model and your repositories. An MCP server cannot do more than its credential allows, so a read-only, single-repository token turns a bad tool call into a failed tool call. Issue the narrowest token that still makes the agent useful.

Pin the package. ["-y", "@modelcontextprotocol/server-github"] resolves the latest version on every activation. That is convenient in development and a supply-chain dependency in production — whoever publishes that package can change what runs inside your silo. Pin an exact version, or run the server from an image you control:

Pinned Stdio server
{
    "Name": "GitHub",
    "TransportType": "Stdio",
    "Command": "npx",
    "Arguments": ["-y", "@modelcontextprotocol/[email protected]"],
    "Env": { "GITHUB_TOKEN": "ghp_xxx" }
}

Keep secrets out of the config file. The literal "ghp_xxx" above is fine in a blog post and wrong in a repository. Resolve tokens from your configuration provider or key vault and connect in code, which is one of the reasons the code-driven path exists.

For Http transport the process risk disappears and a network one replaces it: the silo makes outbound calls to a third-party endpoint carrying a bearer token, and the tools it exposes can change without a deployment on your side. Treat a remote MCP endpoint the way you would treat any other upstream dependency with credentials attached.

MCP Server or FabrCore Plugin?

MCP is not automatically the right answer just because it is the newer one. FabrCore plugins run in-process, and that difference decides most cases:

Use an MCP server whenUse a plugin when
A capable server already exists for the service The tool is specific to your domain or data model
The integration is maintained by someone else The tool needs your DI container, database context, or agent state
Process isolation is a feature, not a cost Per-activation process startup is too expensive
The tool surface changes independently of your release cycle You want compile-time types and a testable seam

The distinction matters more at scale than it looks. A Stdio server is connected per agent grain activation, so a thousand active agents each configured with a Stdio MCP server is a thousand child processes. In-process plugins have no such cost. When we built Guardian — a per-user agent assigned to every person we support — that arithmetic is exactly why its tools are in-process plugins rather than MCP servers.

The two are not exclusive. ResolveConfiguredToolsAsync() returns plugin tools, standalone tools, and MCP tools in one list, so an agent can use a maintained GitHub MCP server for repository access and your own plugin for the business logic that only you have.

How Failures Actually Behave

MCP servers are external processes and remote endpoints, so they fail in ways in-process code does not. FabrCore is explicit about what happens in each case:

ScenarioBehavior
Config-driven server fails to connectWarning logged; the agent starts without that server's tools
Code-driven server fails to connectException propagates to your OnInitialize
Server process dies after connectingTool invocations throw; the model sees the failure and adapts

The first row is the one to think hardest about. Graceful degradation means an agent whose GitHub server failed to start is still online and still answering — it has simply, silently, lost the ability to do the thing it was created for. That is usually the right default for availability and a poor default for correctness, and it is why config-driven MCP needs monitoring rather than trust.

Connected servers surface as McpServerConnections in the agent's custom health metrics:

Health check
GET /api/agents/{handle}/health?detailLevel=Full

Alert on the count dropping below what the agent's configuration declares, and a failed connection becomes a page instead of a mystery. If a missing tool should be fatal, use the code-driven path and let the exception stop activation — that choice is the practical difference between the two modes, not the syntax.

Connections themselves need no cleanup code: MCP clients are disposed automatically when the agent grain deactivates.

Why This Matters

Before MCP support, every external integration meant writing custom tool code. Need GitHub access? Write a plugin. Need filesystem tools? Write another plugin. Need a database? Another plugin. Each one with its own authentication handling, error management, and maintenance burden.

With MCP, the ecosystem does the heavy lifting. Hundreds of MCP servers already exist for popular services, and more are being built every day. Your FabrCore agents can now tap into all of them with a few lines of configuration.

And because MCP tools are standard AITool instances, they work seamlessly with everything else in FabrCore — CreateChatClientAgent(), ChatOptions.Tools, health diagnostics, the full stack.

Get Started

MCP server support is available now. Check out the full documentation for the complete McpServerConfig reference, error behavior details, and health diagnostics integration.


Eric Brasher

Builder of FabrCore and OpenCaddis.