-
Notifications
You must be signed in to change notification settings - Fork 0
Add MCP server support — expose Repl apps as AI agent tools #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
e4d9401
Add Core metadata enrichment for MCP server support
carldebilly 62d1d07
Add Repl.Mcp package with MCP server integration
carldebilly ac7a52f
Add MCP interaction channel and pipeline dispatch
carldebilly 33440e6
Add MCP resources, prompts, and sample app
carldebilly b899674
Wire MCP progress notifications to WriteProgressAsync
carldebilly 3ca16e7
Add elicitation, sampling, MCP logging, and list_changed support
carldebilly b4fae04
Fix CI pack failure and make NuGet publish resilient
carldebilly 9e9a793
Add MCP server documentation and fix API naming
carldebilly fb9456b
Improve annotation docs and wire LongRunning to MCP tasks
carldebilly 25a7383
Fix resources and prompts not registered with MCP server
carldebilly 0a63bc1
Add MCP end-to-end integration tests and fix list_changed scope
carldebilly 51add07
Fail NuGet publish step when all packages fail
carldebilly 8c17217
Address PR review: fix bugs, exclusions, and Programmatic channel
carldebilly 776487d
Add opt-in resource/prompt fallback to tools and AutoPromoteReadOnly
carldebilly d786f9b
Remove unused capturedPath variable and unused test binding
carldebilly 04e8094
Fix AskConfirmation fail mode and remove dead answer: handling
carldebilly c2cbfdf
Fix thread safety and CI secret handling
carldebilly c3f1759
Fix Programmatic channel resolution and session isolation
carldebilly 23b333a
Document output behavior and token cost in MCP mode
carldebilly 84ef2fb
Fix Hidden/AutomationHidden leaking into resources and prompts,
carldebilly 40012e3
Use slash separator for resource URIs regardless of ToolNamingSeparator
carldebilly 3cf5bce
Fix optional segment tokens, collection schema, prompt collisions,
carldebilly 4b21d1f
Remove numeric index parsing from choice resolution — match by name only
carldebilly c6b9379
Fix prompt parameter exposure, error surfacing, and context Details
carldebilly 3c97c5b
Add end-to-end fallback tests via real McpServerHandler pipeline
carldebilly 1cbd6a0
Clear stale routes on invalidation, surface resource errors, add IEnu…
carldebilly b455592
Align MCP interaction channel with console channel behavior
carldebilly ebe4cdc
Add injectable transport factory and interaction error tests
carldebilly e3053ec
Fix review findings: IsProgrammatic restore, DestructiveHint, confirm…
carldebilly a8fc449
Add debounce and concurrent session tests, use injectable TimeProvider
carldebilly 296954d
Fix parameterized resources passing empty arguments dictionary
carldebilly 6e374d7
Add configurable ResourceUriScheme for MCP resource URIs
carldebilly 25fe7d7
Fix timer crash resilience, optimistic route rebuild, prompt server p…
carldebilly 310e630
Make AskConfirmationAsync defaultValue nullable for consistent fallback
carldebilly 624c77e
Add BuildMcpServerOptions for custom transport and HTTP integration
carldebilly f4db7ab
Document multi-session pattern for stdio-over-anything transports
carldebilly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| # MCP Advanced: Custom Transports & HTTP Integration | ||
|
|
||
| This guide covers two advanced integration scenarios beyond the default stdio transport. | ||
|
|
||
| > **Prerequisite**: read [mcp-server.md](mcp-server.md) first for the basics of exposing a Repl app as an MCP server. | ||
|
|
||
| ## Scenario A: Stdio-over-anything | ||
|
|
||
| The MCP protocol is JSON-RPC over stdin/stdout. The `TransportFactory` option lets you replace the physical transport while keeping the same protocol — useful for WebSocket bridges, named pipes, SSH tunnels, etc. | ||
|
|
||
| ### How it works | ||
|
|
||
| `TransportFactory` receives the server name and an I/O context, and returns an `ITransport`. The MCP server uses this transport instead of `StdioServerTransport`. | ||
|
|
||
| ```csharp | ||
| app.UseMcpServer(o => | ||
| { | ||
| o.TransportFactory = (serverName, io) => | ||
| { | ||
| // Bridge a WebSocket connection to MCP via streams. | ||
| var (inputStream, outputStream) = CreateWebSocketBridge(); | ||
| return new StreamServerTransport(inputStream, outputStream, serverName); | ||
| }; | ||
| }); | ||
| ``` | ||
|
|
||
| The app still launches via `myapp mcp serve` — the framework handles the full MCP lifecycle (tool registration, routing invalidation, shutdown). This approach gives you **one session per process**. | ||
|
|
||
| ### Multi-session (accept N connections) | ||
|
|
||
| For multiple concurrent sessions over a custom transport (e.g. a WebSocket listener accepting many clients), use `BuildMcpServerOptions` to build the options once, then create a server per connection: | ||
|
|
||
| ```csharp | ||
| var mcpOptions = app.Core.BuildMcpServerOptions(); | ||
|
|
||
| // For each incoming WebSocket connection: | ||
| async Task HandleConnectionAsync(Stream input, Stream output, CancellationToken ct) | ||
| { | ||
| var transport = new StreamServerTransport(input, output, "my-server"); | ||
| var server = McpServer.Create(transport, mcpOptions); | ||
| await server.RunAsync(ct); | ||
| await server.DisposeAsync(); | ||
| } | ||
| ``` | ||
|
|
||
| Each session is fully isolated — tool invocations run in separate `AsyncLocal` scopes with their own I/O streams, just like hosted sessions. | ||
|
|
||
| ### When to use | ||
|
|
||
| - You have a non-stdio transport (WebSocket, named pipe, TCP) that carries the standard MCP JSON-RPC protocol | ||
| - Single-session: use `TransportFactory` via `mcp serve` (simplest) | ||
| - Multi-session: use `BuildMcpServerOptions` + one `McpServer.Create` per connection | ||
|
|
||
| ## Scenario B: MCP-over-HTTP (Streamable HTTP) | ||
|
|
||
| The MCP spec defines a native HTTP transport: POST for client→server messages, GET/SSE for server→client streaming, with session management. This requires an HTTP host (typically ASP.NET Core) rather than a CLI command. | ||
|
|
||
| ### How it works | ||
|
|
||
| `BuildMcpServerOptions()` constructs the full `McpServerOptions` (tools, resources, prompts, capabilities) from your Repl app's command graph — without starting a server. You pass these options to the MCP C# SDK's HTTP integration. | ||
|
|
||
| ```csharp | ||
| var app = ReplApp.Create(); | ||
| app.Map("greet {name}", (string name) => $"Hello, {name}!"); | ||
| app.Map("status", () => "all systems go").ReadOnly(); | ||
|
|
||
| // Build MCP options from the command graph. | ||
| var mcpOptions = app.Core.BuildMcpServerOptions(configure: o => | ||
| { | ||
| o.ServerName = "MyApi"; | ||
| o.ResourceUriScheme = "myapi"; | ||
| }); | ||
|
|
||
| // Use with McpServer.Create for a custom HTTP handler... | ||
| var server = McpServer.Create(httpTransport, mcpOptions); | ||
|
|
||
| // ...or pass the collections to ASP.NET Core's MapMcp. | ||
| ``` | ||
|
|
||
| ### Multi-session | ||
|
|
||
| Each HTTP request creates an isolated MCP session. This uses the same mechanism as Repl's hosted sessions: | ||
|
|
||
| - `ReplSessionIO.SetSession()` creates an `AsyncLocal` scope per request | ||
| - Each session has its own output writer, input reader, and session ID | ||
| - Tool invocations are fully isolated — concurrent requests don't interfere | ||
|
|
||
| This is identical to how the framework handles concurrent tool calls in stdio mode (via `McpToolAdapter.ExecuteThroughPipelineAsync`). | ||
|
|
||
| ### When to use | ||
|
|
||
| - You're building a web API that also exposes MCP endpoints | ||
| - You need multiple concurrent MCP sessions (agents connecting via HTTP) | ||
| - You want to integrate with the ASP.NET Core pipeline (auth, middleware, etc.) | ||
|
|
||
| ## Configuration reference | ||
|
|
||
| | Option | Default | Description | | ||
| |--------|---------|-------------| | ||
| | `TransportFactory` | `null` (stdio) | Custom transport factory for Scenario A | | ||
| | `ResourceUriScheme` | `"repl"` | URI scheme for MCP resources (`{scheme}://path`) | | ||
| | `ServerName` | Assembly product name | Server name in MCP `initialize` response | | ||
| | `ServerVersion` | `"1.0.0"` | Server version in MCP `initialize` response | | ||
|
|
||
| See [mcp-server.md](mcp-server.md) for the full configuration reference. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.