Quickstart
Go from zero to a working Ithil gateway with an annotated ASP.NET API in under 10 minutes.
Prerequisites
- .NET 10 SDK
- Docker (for Redis)
- An existing ASP.NET Web API project, or the Ithil sample project
Run Redis
Ithil requires Redis for budget tracking and the semantic cache. Start it with Docker:
docker run -d -p 6379:6379 redisIf you see a long string of letters and numbers printed, Redis is running.
Add Ithil.Hosting to your API
Install the NuGet package:
dotnet add package Ithil.HostingAdd four lines to your existing Program.cs (marked with // ADD THIS):
using Ithil.Generated; // ADD THIS
using Ithil.Hosting; // ADD THIS
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddIthilHosting(); // ADD THIS
// ... your existing services ...
var app = builder.Build();
app.MapControllers();
app.MapIthilSchema(SchemaRegistry.Tools); // ADD THIS
app.Run();Annotate a controller method
Add [AgentTool] to any controller method you want the AI agent to be able to call:
using Ithil.Attributes;
[ApiController]
[Route("api/placeholder")]
public class JsonPlaceholderController(IHttpClientFactory httpClientFactory) : ControllerBase
{
private HttpClient Client => httpClientFactory.CreateClient("jsonplaceholder");
[AgentTool("Returns a single post by ID")] // ADD THIS
[HttpGet("posts/{id:int}")]
public async Task<IActionResult> GetPost(int id) =>
Ok(await Client.GetFromJsonAsync<object>($"posts/{id}"));
}The [AgentTool] attribute is the only change to your existing code. The source generator emits SchemaRegistry at compile time — no reflection, no runtime overhead.
Run Ithil.Gateway
Docker (recommended):
docker run -d \
-p 5100:8080 \
-e Ithil__LicenseKey="your-license-key" \
-e Ithil__Jwt__SigningKey="your-32-byte-or-longer-signing-key" \
-e Ithil__ToolRegistry__DownstreamBaseUrl="http://host.docker.internal:5200" \
-e ConnectionStrings__Redis="host.docker.internal:6379" \
ithilsoftware/gateway:latestManual:
Get a free license key at ithil.software/register before running — the gateway will refuse to start without one.
dotnet run --project src/Ithil.GatewayMinimum appsettings.json for the gateway:
{
"Ithil": {
"LicenseKey": "your-license-key",
"Jwt": {
"SigningKey": "your-32-byte-or-longer-signing-key"
},
"ToolRegistry": {
"DownstreamBaseUrl": "http://localhost:5200"
}
},
"ConnectionStrings": {
"Redis": "localhost:6379"
}
}Verify the tool appears
In development, get a short-lived agent JWT from the gateway’s dev token endpoint:
curl http://localhost:5100/dev/tokenInitialize an MCP session:
curl -si http://localhost:5100/mcp \
-H "Authorization: Bearer <token-from-above>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}'In the response headers, find the Mcp-Session-Id line — it looks like this:
Mcp-Session-Id: ugsxZkcDzylMsjpfYTEc6wCopy that value, then list your tools:
curl -s http://localhost:5100/mcp \
-H "Authorization: Bearer <token-from-above>" \
-H "Mcp-Session-Id: <value-from-Mcp-Session-Id-header>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'You should see your tool listed in the response.
Make a tool call
curl -s http://localhost:5100/mcp \
-H "Authorization: Bearer <token-from-above>" \
-H "Mcp-Session-Id: <value-from-Mcp-Session-Id-header>" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "GetPost",
"arguments": { "id": 1 }
}
}'You should see the post data returned in the response.
What just happened
The gateway received the MCP request, validated the agent’s JWT, checked the agent’s daily token budget, forwarded the call to your ASP.NET API’s GET /api/placeholder/posts/1 endpoint, filtered the response through the privacy rules, and returned the result back to the agent — all transparently.
Next steps
- Connecting AI Clients — wire up Claude Desktop or the OpenAI Codex CLI
- Configuration — full
appsettings.jsonreference - [AgentTool] Reference — all attribute parameters
- Licensing — get a commercial license key