Content
# SharpMCPServer
SharpMCPServer is a .NET 10 MCP platform for real clients, real tools, and real approval gates.
[](https://github.com/haxxornulled/SharpMCPServer/actions/workflows/ci.yml)
[](https://github.com/haxxornulled/SharpMCPServer/actions/workflows/smoke.yml)
[](https://github.com/haxxornulled/SharpMCPServer/actions/workflows/release.yml)
[](LICENSE)
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 a SignalR-backed 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](docs/SPEC_COMPLIANCE.md).
If you only read one doc next, read [docs/GETTING_STARTED.md](docs/GETTING_STARTED.md).
## Pipelines
The GitHub Actions pipeline now matches the repo's actual lanes instead of pretending one build command tells the whole story:
- `CI` restores with locked dependencies, builds the solution, and runs the repository verification lane on pushes and pull requests to `main`.
- `Smoke` is a separate manual workflow dispatch for the explicit smoke lane when you want the full client-facing process checks.
- `Release` packages the host, console client, and chat launcher for tagged `v*.*.*` 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.ps1` followed by `pwsh .\scripts\Test-Smoke.ps1 -Configuration Release` when you want the same shape without waiting on GitHub.
## How to read this repo
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.
## What this repo gives you
| Surface | What it does |
| --- | --- |
| `SharpMCPServer.Host` | Main MCP server host for stdio and loopback Streamable HTTP. |
| `SharpMCPServer.Web` | SignalR-backed 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.
## Dashboard
`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 over SignalR on loopback.
If you want the rationale and boundary rules in one place, read [docs/DASHBOARD.md](docs/DASHBOARD.md).
## Start here
1. Build the repo.
2. Start the host.
3. Ask the server something boring and read-only.
4. Start the chat launcher if you want interactive use.
5. Use the sample client configs for first real-client checks.
```powershell
dotnet build .\SharpMCPServer.slnx -c Debug
dotnet run --project .\SharpMCPServer.Host\SharpMCPServer.Host.csproj
```
```powershell
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 server.info
```
```powershell
dotnet run --project .\SharpMCPServer.ChatLauncher\SharpMCPServer.ChatLauncher.csproj -- --provider lmstudio
```
Swap `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.
## What you can do with it
- 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.
## Common first commands
Once the host is up, these are the first tools people usually try:
```powershell
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 list
```
If 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](docs/SSH_PROFILE_MANAGER.md). That is the repo-owned CLI surface for listing, creating, linking, and deleting SSH profiles.
## Architecture Workflow
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.
### MCP host lane
```mermaid
%%{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.
### Standalone AgentRouter bridge
```mermaid
%%{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.
## Runtime and plugin rules
Plugins may shape behavior.
Plugins may not self-authorize behavior.
All runtime and plugin execution still flows through SentinelMCP and the platform tool gateway.
## Real client setup
If you want to hook up Claude Code, VS Code / GitHub Copilot, or Cursor, start with [samples/mcp-clients/README.md](samples/mcp-clients/README.md).
The compatibility checklist lives in [docs/REAL_MCP_CLIENT_COMPATIBILITY.md](docs/REAL_MCP_CLIENT_COMPATIBILITY.md), and first-run staging notes live in [docs/REAL_CLIENT_STAGING.md](docs/REAL_CLIENT_STAGING.md).
## Configuration
The main host knobs live in [SharpMCPServer.Host/appsettings.json](SharpMCPServer.Host/appsettings.json):
- `McpTransport:Http` for loopback HTTP, replay, and authorization.
- `McpWorkspace` for workspace roots, sandbox paths, and byte limits.
- `McpInference` for provider routing and prompt intelligence.
- `McpTools:Ssh` for SSH policy and allow/deny rules.
- `SentinelMCP:ApprovalJwt` for approval token settings.
- `DashboardHub` for the loopback SignalR operator dashboard endpoint and update cadence.
If provider setup is the part you want to get right first, read [docs/INFERENCE_PROVIDERS.md](docs/INFERENCE_PROVIDERS.md) before you start tweaking random JSON.
If you are only using the Python bridge, see [python/README.md](python/README.md) and [docs/INSTALL.md](docs/INSTALL.md).
## Build and test
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.
```powershell
dotnet restore .\SharpMCPServer.slnx
dotnet build .\SharpMCPServer.slnx -c Debug
dotnet test .\SharpMCPServer.slnx -c Debug
```
For the normal end-to-end verification lane, use `pwsh .\scripts\verify-mcp-phase1.ps1`.
## Read next
- [docs/GETTING_STARTED.md](docs/GETTING_STARTED.md)
- [docs/INFERENCE_PROVIDERS.md](docs/INFERENCE_PROVIDERS.md)
- [docs/BUILD_AND_TEST.md](docs/BUILD_AND_TEST.md)
- [docs/TESTING.md](docs/TESTING.md)
- [docs/INSTALL.md](docs/INSTALL.md)
- [docs/WORKSPACE_SANDBOXES.md](docs/WORKSPACE_SANDBOXES.md)
- [docs/WEB_BROWSING.md](docs/WEB_BROWSING.md)
- [docs/CLIENT_INTERACTION_RUNTIME.md](docs/CLIENT_INTERACTION_RUNTIME.md)
- [docs/REAL_CLIENT_STAGING.md](docs/REAL_CLIENT_STAGING.md)
- [docs/REAL_CLIENT_TRANSCRIPT_CAPTURE.md](docs/REAL_CLIENT_TRANSCRIPT_CAPTURE.md)
- [docs/REAL_MCP_CLIENT_COMPATIBILITY.md](docs/REAL_MCP_CLIENT_COMPATIBILITY.md)
- [docs/PROMPT_INTELLIGENCE.md](docs/PROMPT_INTELLIGENCE.md)
- [docs/SPEC_COMPLIANCE.md](docs/SPEC_COMPLIANCE.md)
- [SentinelMCP/README.md](SentinelMCP/README.md)
- [python/README.md](python/README.md)
Connection Info
You Might Also Like
Train-in-Silence
The first Task-Aware MCP server and automated VRAM calculator for LLM...
stacklit
108,000 lines of code. 4,000 tokens of index. One command makes any repo...
AppClaw
AI-powered mobile automation agent — describe what you want in plain...
pdf-mcp
Production-ready MCP server for PDF processing with intelligent caching....
kotadb
Local-only code intelligence API for AI developer workflows (Bun +...
gemini-api-docs-mcp
A remote HTTP MCP server for searching Google Gemini API documentation.