-
Notifications
You must be signed in to change notification settings - Fork 0
Cadenza Mcp
A Model Context Protocol server in a single .cs file. Expose typed Tool, Resource, and Prompt primitives to Claude Desktop, Cursor, VS Code, or any MCP-aware client — no SDK glue, no project tree.
#:sdk Cadenza.Mcp@1.0.15| Base SDK | Microsoft.NET.Sdk |
| Transport | stdio (default) — clients spawn the process |
| Underlying library | ModelContextProtocol |
| AOT-clean | Yes |
#!/usr/bin/env dotnet run
#:sdk Cadenza.Mcp@1.0.15
Tool("read_file", "Read a UTF-8 text file from disk",
(string path) => ReadText(path));
Tool("list_files", "List files matching a glob pattern (e.g., **/*.cs)",
(string pattern) => Glob(pattern).ToArray());
await Run();Cadenza infers the JSON schema for the tool's input from the handler's parameter types and serializes the return value back to the client. Parameter XML comments become argument descriptions in the schema.
Tool(name, description, handler) // expose a callable tool
Resource(uri, name, handler) // expose a readable resource at a fixed URI
Prompt(name, description, handler) // expose a parameterized prompt template
await Run(); // start the MCP server on stdioPlus the shared modules — Fs, Sh, Http, Env, Json. WriteLine is deliberately not exposed — stdout is reserved for the JSON-RPC framing. Use Log.Info / Log.Warn / Log.Error / Log.Debug (they write to stderr).
The handler can be sync or async, with any combination of typed parameters.
Tool("get_weather", "Get current weather for a city",
async (string city) =>
{
var key = Env.Get("OPENWEATHER_API_KEY")
?? throw new InvalidOperationException("OPENWEATHER_API_KEY missing");
return await Http.GetText(
$"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={key}");
});Multiple parameters become a JSON object input:
Tool("search", "Search code in the repo",
(string pattern, string filetype, int maxResults) =>
Glob($"**/*.{filetype}")
.Where(f => ReadText(f).Contains(pattern))
.Take(maxResults)
.ToArray());Expose a known file or computed value at a fixed URI:
Resource("readme://current", "Project README",
() => ReadText("README.md"));
Resource("config://defaults", "Default config",
() => Json.Stringify(new { theme = "dark", verbose = true }, Ctx.Default));Clients can list resources and read them on demand. The handler can be sync or async.
Prompts are parameterized templates the client can invoke (e.g. Claude's "Slash commands"):
Prompt("review_code", "Review the given code for issues",
(string code) => $@"Please review this code for bugs, security, and style:
{code}");
Prompt("explain_diff", "Explain a git diff in plain English",
(string diff, string audience) =>
$"Explain this diff to a {audience}:\n\n{diff}");Never call WriteLine from an MCP stdio server — it corrupts the JSON-RPC stream. Use Log.* instead; Cadenza routes those to stderr:
Log.Info("Cadenza.Mcp server starting on stdio");
Log.Warn($"Tool {name} took {ms} ms (>1s budget)");
Log.Error("Upstream API failed", ex);~/Library/Application Support/Claude/claude_desktop_config.json (macOS) / %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"files": {
"command": "dotnet",
"args": ["run", "/absolute/path/to/mcp-files.cs"]
}
}
}Settings → MCP:
{
"mcpServers": {
"files": {
"command": "dotnet",
"args": ["run", "/absolute/path/to/mcp-files.cs"]
}
}
}The C# extension's MCP integration accepts the same JSON shape. Drop the snippet into .vscode/mcp.json (workspace) or the global MCP config.
Ship the MCP server as an OCI image and have the client launch it via docker run -i (-i is required so stdin/stdout pipe through):
{
"mcpServers": {
"files": {
"command": "docker",
"args": ["run", "-i", "--rm", "my-org/files:1.0"]
}
}
}See Deployment Container.
- Wrapping a database, internal API, or filesystem area as MCP tools
- Prototyping MCP servers before promoting to a full project
- Hobby integrations where one
.csis the whole product
- You need an OpenAI-compatible chat endpoint instead of MCP → use Cadenza Agent
- You're serving HTTP responses to humans → use Cadenza Web
-
mcp-files.cs—Toolonly, minimal -
mcp-extended.cs—Tool+Resource+Prompttogether
See Samples for the full annotated list.
-
Tier 1 API —
Tool,Resource,Prompt,Run - Cadenza Agent — same idea, but with chat semantics and an LLM behind it
- MCP spec
Cadenza · MIT · .NET 10+ · github.com/rkttu/cadenza · No orchestra. No project. Just one file, playing solo.