Brightmetrics.McpServer
1.0.4
{ "servers": { "Brightmetrics.McpServer": { "type": "stdio", "command": "dnx", "args": ["Brightmetrics.McpServer@1.0.4", "--yes"] } } }
.vscode/mcp.json settings file.
dotnet tool install --global Brightmetrics.McpServer --version 1.0.4
dotnet new tool-manifest
dotnet tool install --local Brightmetrics.McpServer --version 1.0.4
#tool dotnet:?package=Brightmetrics.McpServer&version=1.0.4
nuke :add-package Brightmetrics.McpServer --version 1.0.4
Brightmetrics.McpServer
A modular MCP server hosting multiple tools for AI clients. Built on .NET generic host with stdio transport.
Tech Stack
- Runtime: .NET 10+
- Transport: stdio (stdin/stdout) — no HTTP port required
- Persistence: SQLite (in-memory, shared-cache) via Entity Framework Core
- Semantic analysis: Roslyn (
Microsoft.CodeAnalysis.Workspaces.MSBuild)
Tools
| Tool | Description |
|---|---|
find_definition |
Find the source definition(s) of a C# symbol in a .sln using Roslyn (F12 / Go to Definition) |
get_last_heartbeat |
Returns the timestamp of the most recent heartbeat recorded by the background service |
ping |
Echoes pong in response to ping — simple connectivity check |
Project Structure
McpServer/
├── McpServer.csproj
├── Program.cs # Startup + tool registration
└── Tools/
├── F12/ # find_definition tool (Roslyn semantic analysis)
│ ├── F12Service.cs
│ └── F12Tools.cs
├── Heartbeats/ # Heartbeat tool + background service
│ ├── Heartbeat.cs
│ ├── HeartbeatDbContext.cs
│ ├── HeartbeatService.cs
│ └── HeartbeatTools.cs
└── Ping/ # Ping tool
└── PingTools.cs
Tool: find_definition
Uses Roslyn's full semantic model to locate the source declaration of any C# symbol — the equivalent of pressing F12 (Go to Definition) in Visual Studio.
Performance: The solution is loaded once on the first call and kept open in memory for the lifetime of the server process. Subsequent lookups are fast.
Parameters
| Parameter | Type | Description |
|---|---|---|
solutionPath |
string | Absolute path to a .sln file, or a shortcut key (see below) |
symbolName |
string | Exact symbol name to find (case-sensitive) |
Shortcuts
Pass "-env" as the solutionPath to resolve the path from the F12_SLN_PATH environment variable:
export F12_SLN_PATH="C:\path\to\your\solution.sln"
If F12_SLN_PATH is not set and "-env" is used, the call will fail with a NotImplementedException (automatic solution discovery is not yet implemented).
Response
Returns a JSON array. Each element represents one source location where the symbol is declared:
[
{
"Symbol": "MyController",
"Container": "global",
"Kind": "NamedType",
"File": "C:\\src\\projects\\BrightMetricsWeb\\Controllers\\MyController.cs",
"Line": 12,
"Character": 1
}
]
On error (solution not found, Roslyn failure, etc.):
{ "error": "Solution file not found: C:\path\to\missing.sln" }
Requirements
The server machine must have Visual Studio or the .NET SDK installed so that MSBuild can be located at startup. If no SDK instance is found, find_definition calls will fail with a workspace error.
Run Locally
cd McpServer
dotnet run
The server communicates over stdin/stdout. It produces no HTTP endpoint — connect to it via an MCP client or the MCP inspector (see below).
Test with MCP Inspector
npx @modelcontextprotocol/inspector dotnet run --project McpServer.csproj
Configure in Claude Code / MCP Client
Create a .mcp.json file at the repo root for Claude Code (or another MCP client). For example, the following configuration runs the server via dnx (dotnet tool runner) and passes F12_SLN_PATH from a prompted input:
{
"mcpServers": {
"Brightmetrics.McpServer": {
"type": "stdio",
"command": "dnx",
"args": ["Brightmetrics.McpServer@1.0.3", "--yes"],
"env": {
"F12_SLN_PATH": "<absolute path to your .sln>"
}
}
}
}
Pack & Publish
Version is tracked in three places — bump all three before packing:
| File | Field |
|---|---|
McpServer.csproj |
<PackageVersion> |
.mcp/server.json |
top-level "version" and packages[0].version |
.mcp.json |
args entry "Brightmetrics.McpServer@<version>" |
Build a local package
dotnet pack McpServer.csproj --configuration Release --output ./nupkg
Install & run from a local package
# Install globally from the local nupkg folder
dotnet tool install -g --add-source ./nupkg Brightmetrics.McpServer
# Run it (reads from stdin, writes to stdout)
brightmetrics-mcp
# Uninstall
dotnet tool uninstall -g Brightmetrics.McpServer
Publish to NuGet.org (MCP registry)
The .csproj is configured with <PackageType>McpServer</PackageType>, which marks the package as an MCP server in the NuGet gallery and makes it discoverable by MCP-aware clients.
Get an API key at https://www.nuget.org/account/apikeys. Scope it to
Brightmetrics.McpServerwith push permissions.Store the key (once):
dotnet nuget add source https://api.nuget.org/v3/index.json \ --name nuget.org \ --username ahape \ --password <YOUR_API_KEY>Pack (bump version in the three files listed above first):
dotnet pack McpServer.csproj --configuration Release --output ./nupkgPush:
dotnet nuget push ./nupkg/Brightmetrics.McpServer.<version>.nupkg \ --api-key <YOUR_API_KEY> \ --source https://api.nuget.org/v3/index.json
Once published, anyone can install and run the server via dnx:
dnx Brightmetrics.McpServer --yes
Adding a New Tool
- Create
Tools/<ToolName>/<ToolName>Tools.cswith a public class and methods decorated with[McpServerTool]. - If the tool needs long-lived state, create a corresponding service and register it as a singleton in
Program.cs. - Register the tool class in
Program.cs:builder.Services .AddMcpServer() .WithStdioServerTransport() .WithTools<HeartbeatTools>() .WithTools<PingTools>() .WithTools<F12Tools>() .WithTools<YourNewTools>(); // add here
TODO
- Follow the steps from this article on how to configure GitHub Copilot to use this MCP server
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.