MCPApplication service as a tool
MCP

Application service as a tool

Expose a C# service through a named MCP tool with a clear input contract.

Keep the operation in an application service and describe how clients call it through the MCP adapter. This example measures text without requiring a model or external API.

Create the host and tool

Install Runiq.AI.Mcp and use this complete Program.cs in an ASP.NET Core project:

Program.cs
using ModelContextProtocol.Server;
using Runiq.AI.Mcp;
using System.ComponentModel;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<TextLengthService>();
builder.Services.AddRuniqMcp();

var app = builder.Build();
app.MapRuniqMcp();
app.Run();

/// <summary>Calculates text length for the application.</summary>
public sealed class TextLengthService
{
    /// <summary>Returns the UTF-16 code unit count.</summary>
    public int Count(string text)
    {
        ArgumentNullException.ThrowIfNull(text);
        return text.Length;
    }
}

/// <summary>Exposes text inspection through MCP.</summary>
[McpServerToolType]
public sealed class TextLengthMcpTool
{
    private readonly TextLengthService service;

    /// <summary>Creates an adapter for the text service.</summary>
    public TextLengthMcpTool(TextLengthService service)
    {
        this.service = service;
    }

    /// <summary>Returns the UTF-16 length of the supplied text.</summary>
    [McpServerTool(Name = "text_length")]
    [Description("Returns the number of UTF-16 code units in the supplied text.")]
    public int Count(
        [Description("The text to measure.")] string text)
    {
        return service.Count(text);
    }
}

The explicit text_length name gives clients a stable identifier. "Hello Runiq" returns 11; an empty string returns 0. UTF-16 length does not count visible characters for every language or emoji.

Design the contract

PartResponsibility
NameIdentify one callable operation.
DescriptionExplain what the operation returns.
ParametersDescribe the required input.
ServiceExecute business rules, validation, and data access.

This adapter lives in the entry assembly so default discovery can find it. The same service can also be called from a controller or a Runiq agent tool, with its own exposure rules.

Continue with Studio testing.

On this page