SharpMCPServer is a .NET 10 MCP platform for real clients, real tools, and real approval gates.
It runs a host that serves stdio and loopback Streamable HTTP, keeps workspace writes inside explicit sandboxes, routes inference through provider adapters, exposes SSH and AgentRouter tools from the host, ships an in-process Blazor operator dashboard in SharpMCPServer.Web, and keeps the Python-facing AgentRouter bridge in a separate NativeAOT runtime lane instead of blurring that boundary behind CLR tricks.
If you want a toy demo, there are easier repos. If you want something you can point actual clients at and still explain to another engineer later, this is the point.
Protocol baseline: MCP 2025-11-25. The implementation matrix lives in docs/SPEC_COMPLIANCE.md. If you only read one doc next, read docs/GETTING_STARTED.md.
The GitHub Actions pipeline now matches the repo's actual lanes instead of pretending one build command tells the whole story:
CIrestores with locked dependencies, builds the solution, and runs the repository verification lane on pushes and pull requests tomain.Smokeis a separate manual workflow dispatch for the explicit smoke lane when you want the full client-facing process checks.Releasepackages the host, console client, and chat launcher for taggedv*.*.*releases, then publishes the exact artifacts that were built.- Dependabot watches both GitHub Actions and NuGet so workflow and package drift does not sit unnoticed.
- The local equivalent remains
pwsh .\scripts\verify-mcp-phase1.ps1followed bypwsh .\scripts\Test-Smoke.ps1 -Configuration Releasewhen you want the same shape without waiting on GitHub.
If code, tests, AGENTS.md, and other docs disagree, use that order.
The code wins. The tests prove it. AGENTS.md sets repo rules. Docs explain the current shape, not the other way around.
| Surface | What it does |
|---|---|
SharpMCPServer.Host |
Main MCP server host for stdio and loopback Streamable HTTP. |
SharpMCPServer.Web |
In-process Blazor operator dashboard for approvals, workspace state, tools, logs, and host health. |
SharpMCPServer.Client.Console |
Direct console client for tool calls, chat mode, and protocol checks. |
SharpMCPServer.ChatLauncher |
Repo-owned wrapper that launches the console with sane defaults. |
SharpMCPServer.Application |
MCP tool, prompt, resource, and task handlers. |
SharpMCPServer.Workspace |
Workspace roots, sandbox persistence, patching, and file policy. |
SharpMCPServer.Tools.Workspace |
Workspace tool surface exposed over MCP. |
SharpMCPServer.Inference.* and SharpMCPServer.Tools.Inference |
Provider routing, prompt intelligence, and inference tool exposure. |
SharpMCPServer.Ssh, SharpMCPServer.Tools.Ssh, and SharpMCPServer.ExecutionPlugins.Ssh |
SSH policy, execution runtime, and SSH-backed AgentRouter execution. |
SharpMCPServer.AgentRouter.* |
Host-owned AgentRouter planning, routing, approval, and execution control plane. |
SentinelMCP/ |
Tool approval, caller binding, audit logging, and security policy enforcement. |
python/ and SharpMCPServer.AgentRouter.PythonBridge.Native |
Standalone NativeAOT AgentRouter bridge and stdlib-only Python wrapper. |
samples/mcp-clients/ |
Safe starter configs for Claude Code, VS Code / Copilot, and Cursor. |
scripts/ |
Verification, smoke, capture, release, and sync scripts. |
IDE extension concepts live under product-concepts/ide-extensions/ and are intentionally outside the main solution.
SharpMCPServer.Web is the operator dashboard.
It exists so operators can see approvals, workspace state, tools, logs, and host health without turning MCP traffic into a UI transport. The UI is a live operator surface, not a second host.
The boundary stays explicit: the web app observes and orchestrates, the host executes. The dashboard connects to the running host through typed host services in the same process.
If you want the rationale and boundary rules in one place, read docs/DASHBOARD.md.
- Build the repo.
- Start the host.
- Ask the server something boring and read-only.
- Start the chat launcher if you want interactive use.
- Use the sample client configs for first real-client checks.
dotnet build .\SharpMCPServer.slnx -c Debug
dotnet run --project .\SharpMCPServer.Host\SharpMCPServer.Host.csprojdotnet run --project .\SharpMCPServer.Client.Console\SharpMCPServer.Client.Console.csproj -- `
--server-path dotnet `
--server-arg .\SharpMCPServer.Host\bin\Debug\net10.0\SharpMCPServer.Host.dll `
--working-directory .\SharpMCPServer.Host\bin\Debug\net10.0 `
--tool server.infodotnet run --project .\SharpMCPServer.ChatLauncher\SharpMCPServer.ChatLauncher.csproj -- --provider lmstudioSwap lmstudio for ollama if that is the local provider you actually have running. Add --allow-workspace-write only when you intentionally want to test write approval and audit behavior.
- Talk to a real MCP host over stdio or Streamable HTTP.
- Use the Blazor dashboard to see live host state, approvals, tools, and logs without mixing presentation concerns into protocol traffic.
- Inspect workspace roots, read files, apply patches, and manage sandboxes without turning the server into a machine-wide filesystem API.
- Route inference through local or remote providers with explicit trust boundaries, then move from LM Studio / Ollama to OpenAI, Anthropic, or Codex when the project needs it.
- Browse public URLs and GitHub content with bounded, read-only fetch tools instead of turning the host into a general crawler.
- Use SSH as a constrained tool surface instead of a free-form shell dump.
- Run AgentRouter workflows through a separate control plane instead of pretending they are just chat prompts.
- Manage SSH profiles through the repo-owned CLI instead of hand-editing ad hoc JSON or exposing secrets in tool arguments.
- Bridge Python into the AgentRouter runtime through a NativeAOT boundary that stays boring on purpose.
Once the host is up, these are the first tools people usually try:
dotnet run --project .\SharpMCPServer.Client.Console\SharpMCPServer.Client.Console.csproj -- `
--server-path dotnet `
--server-arg .\SharpMCPServer.Host\bin\Debug\net10.0\SharpMCPServer.Host.dll `
--working-directory .\SharpMCPServer.Host\bin\Debug\net10.0 `
--tool workspace.roots.list
dotnet run --project .\SharpMCPServer.Client.Console\SharpMCPServer.Client.Console.csproj -- `
--server-path dotnet `
--server-arg .\SharpMCPServer.Host\bin\Debug\net10.0\SharpMCPServer.Host.dll `
--working-directory .\SharpMCPServer.Host\bin\Debug\net10.0 `
--tool inference.providers.list
dotnet run --project .\SharpMCPServer.Client.Console\SharpMCPServer.Client.Console.csproj -- `
--server-path dotnet `
--server-arg .\SharpMCPServer.Host\bin\Debug\net10.0\SharpMCPServer.Host.dll `
--working-directory .\SharpMCPServer.Host\bin\Debug\net10.0 `
--tool web.fetch --arguments {"url":"https://example.com"}
dotnet run --project .\SharpMCPServer.Client.Console\SharpMCPServer.Client.Console.csproj -- `
--server-path dotnet `
--server-arg .\SharpMCPServer.Host\bin\Debug\net10.0\SharpMCPServer.Host.dll `
--working-directory .\SharpMCPServer.Host\bin\Debug\net10.0 `
--tool ssh.profiles.list
dotnet run --project .\SharpMCPServer.Client.Console\SharpMCPServer.Client.Console.csproj -- `
--server-path dotnet `
--server-arg .\SharpMCPServer.Host\bin\Debug\net10.0\SharpMCPServer.Host.dll `
--working-directory .\SharpMCPServer.Host\bin\Debug\net10.0 `
--ssh-profile listIf prompt intelligence is configured, try prompt.intelligence.analyze or prompt.intelligence.optimize after that.
For SSH profile creation and maintenance, see docs/SSH_PROFILE_MANAGER.md. That is the repo-owned CLI surface for listing, creating, linking, and deleting SSH profiles.
The boundary matters more than the amount of code.
There are two runtime lanes in this repo:
- the MCP host lane, which real MCP clients talk to
- the standalone AgentRouter bridge lane, which Python uses directly
SharpMCPServer.ChatLauncher is a wrapper around the console client. It does not replace the host.
%%{init: {'theme':'dark','flowchart': {'curve': 'basis'}, 'themeVariables': {'background': '#0b0f14', 'primaryColor': '#111827', 'primaryBorderColor': '#94a3b8', 'primaryTextColor': '#f8fafc', 'secondaryColor': '#111827', 'tertiaryColor': '#111827', 'lineColor': '#cbd5e1', 'fontFamily': 'ui-sans-serif, system-ui, sans-serif'}}}%%
flowchart TB
classDef client fill:#0f172a,stroke:#818cf8,color:#f8fafc,stroke-width:1.5px;
classDef edge fill:#0b1f2a,stroke:#22d3ee,color:#f8fafc,stroke-width:1.5px;
classDef core fill:#111827,stroke:#94a3b8,color:#f8fafc,stroke-width:1.5px;
classDef tool fill:#052e16,stroke:#4ade80,color:#dcfce7,stroke-width:1.5px;
classDef policy fill:#1f2937,stroke:#fb923c,color:#f8fafc,stroke-width:1.5px;
classDef external fill:#1e1b4b,stroke:#c084fc,color:#f5f3ff,stroke-width:1.5px;
subgraph Clients["Client entry points"]
direction LR
Console([SharpMCPServer.Client.Console]):::client
Chat([SharpMCPServer.ChatLauncher]):::client
Real([Claude Code / VS Code / Cursor]):::client
end
subgraph Host["MCP host"]
direction TB
Edge([stdio or loopback Streamable HTTP]):::edge
Core([SharpMCPServer.Host<br/>Application + Infrastructure + session state]):::core
Tools([Workspace / Inference / SSH / AgentRouter tools]):::tool
end
subgraph Governance["Policy and approvals"]
direction TB
Sentinel([SentinelMCP]):::policy
Approval([approval tokens and audit]):::policy
end
subgraph Capabilities["Host-owned capabilities"]
direction LR
Workspace([Workspace sandboxes]):::external
Inference([Local and remote inference providers]):::external
Ssh([SSH execution]):::external
Router([AgentRouter runtime]):::external
end
Console --> Edge
Chat --> Console
Real --> Edge
Edge --> Core --> Tools
Tools --> Workspace
Tools --> Inference
Tools --> Ssh
Tools --> Router
Tools -. approval-gated work .-> Sentinel
Sentinel --> Approval
The host owns transport, session state, tool composition, and policy enforcement. It does not consume the Python bridge lane.
%%{init: {'theme':'dark','flowchart': {'curve': 'basis'}, 'themeVariables': {'background': '#0b0f14', 'primaryColor': '#111827', 'primaryBorderColor': '#94a3b8', 'primaryTextColor': '#f8fafc', 'secondaryColor': '#111827', 'tertiaryColor': '#111827', 'lineColor': '#cbd5e1', 'fontFamily': 'ui-sans-serif, system-ui, sans-serif'}}}%%
flowchart LR
classDef client fill:#0f172a,stroke:#818cf8,color:#f8fafc,stroke-width:1.5px;
classDef bridge fill:#1e1b4b,stroke:#c084fc,color:#f5f3ff,stroke-width:1.5px;
classDef router fill:#052e16,stroke:#4ade80,color:#dcfce7,stroke-width:1.5px;
Python([python/]):::client
Native([SharpMCPServer.AgentRouter.PythonBridge.Native]):::bridge
Router([AgentRouter runtime]):::router
Python --> Native --> Router
This lane is separate from the MCP host. It is the Python-facing NativeAOT path for AgentRouter consumers.
Plugins may shape behavior.
Plugins may not self-authorize behavior.
All runtime and plugin execution still flows through SentinelMCP and the platform tool gateway.
If you want to hook up Claude Code, VS Code / GitHub Copilot, or Cursor, start with samples/mcp-clients/README.md.
The compatibility checklist lives in docs/REAL_MCP_CLIENT_COMPATIBILITY.md, and first-run staging notes live in docs/REAL_CLIENT_STAGING.md.
The main host knobs live in SharpMCPServer.Host/appsettings.json:
McpTransport:Httpfor loopback HTTP, replay, and authorization.McpWorkspacefor workspace roots, sandbox paths, and byte limits.McpInferencefor provider routing and prompt intelligence.McpTools:Sshfor SSH policy and allow/deny rules.SentinelMCP:ApprovalJwtfor approval token settings.Dashboardfor the loopback operator dashboard endpoint and refresh cadence.
If provider setup is the part you want to get right first, read docs/INFERENCE_PROVIDERS.md before you start tweaking random JSON.
If you are only using the Python bridge, see python/README.md and docs/INSTALL.md.
This is the part where the repo stops being charming and starts being honest. If the build or tests disagree with the prose, trust the command output and fix the thing that is actually broken.
dotnet restore .\SharpMCPServer.slnx
dotnet build .\SharpMCPServer.slnx -c Debug
dotnet test .\SharpMCPServer.slnx -c DebugFor the normal end-to-end verification lane, use pwsh .\scripts\verify-mcp-phase1.ps1.
- docs/GETTING_STARTED.md
- docs/INFERENCE_PROVIDERS.md
- docs/BUILD_AND_TEST.md
- docs/TESTING.md
- docs/INSTALL.md
- docs/WORKSPACE_SANDBOXES.md
- docs/WEB_BROWSING.md
- docs/CLIENT_INTERACTION_RUNTIME.md
- docs/REAL_CLIENT_STAGING.md
- docs/REAL_CLIENT_TRANSCRIPT_CAPTURE.md
- docs/REAL_MCP_CLIENT_COMPATIBILITY.md
- docs/PROMPT_INTELLIGENCE.md
- docs/SPEC_COMPLIANCE.md
- SentinelMCP/README.md
- python/README.md