diff --git a/docs/mcp-overview.md b/docs/mcp-overview.md index 931734e..3cdee8f 100644 --- a/docs/mcp-overview.md +++ b/docs/mcp-overview.md @@ -31,6 +31,7 @@ myapp # still works as CLI / interactive REPL One command graph. CLI, REPL, remote sessions, and AI agents — all from the same code. > `UseMcpServer()` registers a hidden `mcp serve` context. The tool list is built lazily when an agent connects, so it sees all commands regardless of registration order. +> Repl.Mcp is the component that lets your app become an MCP server; it is not itself the MCP server you configure in an agent host. ## What it does @@ -105,7 +106,7 @@ Most MCP clients use the same format: } ``` -See [mcp-reference.md](mcp-reference.md#agent-configuration) for all client-specific paths and formats (Claude Desktop, Claude Code, VS Code Copilot, Cursor, MCP Inspector). +See [mcp-reference.md](mcp-reference.md#agent-configuration) for all client-specific paths and formats (Claude Desktop, Claude Code, VS Code Copilot, Cursor, Cline, MCP Inspector). For a complete copy/paste sample, see [sample 08 — Build an MCP Server with Repl.Mcp](../samples/08-mcp-server/). ## What most apps need vs what few apps need diff --git a/docs/mcp-reference.md b/docs/mcp-reference.md index d6f9954..95a0cc5 100644 --- a/docs/mcp-reference.md +++ b/docs/mcp-reference.md @@ -327,7 +327,11 @@ app.UseMcpServer(o => ## Agent configuration -### Claude Desktop +Agent hosts configure the app or tool you built with Repl.Mcp. They do not install Repl.Mcp directly. + +Prefer a stable executable command, such as a published `dotnet tool`, for shared team configs. When documenting a local sample, use an absolute path to the sample project because most hosts do not launch from your repository root. + +### Generic MCP client / Claude Desktop **File:** `~/.config/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows) @@ -342,24 +346,21 @@ app.UseMcpServer(o => } ``` +For a local sample project, use the same shape with `dotnet run --project /absolute/path/to/project.csproj -- mcp serve`. + ### Claude Code -**File:** `~/.claude.json` or project `.claude/settings.json` +Claude Code can use a command registration flow when available: -```json -{ - "mcpServers": { - "myapp": { - "command": "myapp", - "args": ["mcp", "serve"] - } - } -} +```bash +claude mcp add myapp -- myapp mcp serve ``` -### VS Code (GitHub Copilot) +If your Claude Code version uses settings files instead, use the generic `mcpServers` JSON shape above in user or project settings. + +### VS Code / GitHub Copilot -**File:** `.vscode/mcp.json` (workspace) or `~/.mcp.json` (global) +**File:** `.vscode/mcp.json` (workspace) ```json { @@ -373,6 +374,12 @@ app.UseMcpServer(o => } ``` +VS Code also supports command-line registration: + +```bash +code --add-mcp '{"name":"myapp","command":"myapp","args":["mcp","serve"]}' +``` + ### Cursor **File:** `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global) @@ -388,6 +395,19 @@ app.UseMcpServer(o => } ``` +### Cline + +Use Cline's MCP settings or marketplace flow to add a local stdio server with the same command and args: + +- command: `myapp` +- args: `mcp`, `serve` + +If your Cline version asks for JSON, start from the generic `mcpServers` block above. + +### Complete copy/paste sample + +See [sample 08 — Build an MCP Server with Repl.Mcp](../samples/08-mcp-server/) for Cursor, VS Code, Claude Code, Cline, generic JSON, and MCP Inspector examples. + ### Debugging with MCP Inspector ```bash diff --git a/samples/08-mcp-server/Program.cs b/samples/08-mcp-server/Program.cs index 77b84e7..e9f51b1 100644 --- a/samples/08-mcp-server/Program.cs +++ b/samples/08-mcp-server/Program.cs @@ -7,10 +7,13 @@ // ── A Repl app exposed as an MCP server for AI agents ────────────── // +// Repl.Mcp is the component that lets this sample app become an MCP server. +// Agent hosts install/configure the sample app command, not Repl.Mcp itself. +// // Run interactively: dotnet run // Run as MCP server: dotnet run -- mcp serve // -// Configure in Claude Desktop or VS Code: +// Configure in an MCP host with: // { "command": "dotnet", "args": ["run", "--project", "path/to/08-mcp-server", "--", "mcp", "serve"] } var app = ReplApp.Create(services => diff --git a/samples/08-mcp-server/README.md b/samples/08-mcp-server/README.md index f2cefd2..369b04d 100644 --- a/samples/08-mcp-server/README.md +++ b/samples/08-mcp-server/README.md @@ -1,10 +1,15 @@ -# 08 — MCP Server +# 08 — Build an MCP Server with Repl.Mcp -Expose a Repl command graph as an MCP server for AI agents, including a minimal MCP Apps UI. +This sample shows how to build a real MCP server from a Repl command graph. + +> **Important:** Repl.Mcp is not itself the MCP server you install in an agent host. +> Repl.Mcp is the Repl Toolkit component that lets your app expose its own command graph as an MCP server. +> In this sample, the sample app is the MCP server. ## What this sample shows -- `app.UseMcpServer()` — one line to enable MCP stdio server +- `app.UseMcpServer()` — one line to enable an MCP stdio server for this app +- One command graph exposed as CLI, interactive REPL, and MCP tools/resources/prompts - `contacts paged` — paged structured output for large result sets - `IReplInteractionChannel` in MCP mode — portable notices, warnings, problems, and progress updates - `feedback demo` / `feedback fail` — deterministic progress sequences that are easy to inspect in MCP Inspector @@ -14,42 +19,69 @@ Expose a Repl command graph as an MCP server for AI agents, including a minimal - `.AsMcpAppResource()` — mark a command as a generated HTML MCP App resource - `.WithMcpAppBorder()` / `.WithMcpAppDisplayMode(...)` — add MCP Apps presentation preferences - `.AutomationHidden()` — hide interactive-only commands from agents -- `.WithDetails()` — rich descriptions consumed by agents and documentation tools (not displayed in `--help`) +- `.WithDetails()` — rich descriptions consumed by agents and documentation tools, not displayed in `--help` - `import {file}` — a realistic workflow that combines progress reporting, sampling, elicitation, and duplicate review -## Running +## Run from the repository root + +Use these commands from the root of the `yllibed/repl` repository. -**Interactive REPL:** +### CLI mode ```bash -dotnet run +dotnet run --project samples/08-mcp-server/McpServerSample.csproj -- contacts --json +``` + +Expected shape: + +```json +[ + { + "name": "Alice", + "email": "alice@example.com" + }, + { + "name": "Bob", + "email": "bob@example.com" + } +] ``` -**MCP server mode:** +Try another CLI command: ```bash -dotnet run -- mcp serve +dotnet run --project samples/08-mcp-server/McpServerSample.csproj -- contact 1 --json ``` -**Test with MCP Inspector:** +### Interactive REPL mode ```bash -npx @modelcontextprotocol/inspector dotnet run --project . -- mcp serve +dotnet run --project samples/08-mcp-server/McpServerSample.csproj ``` -Clients with MCP Apps support render the `contacts dashboard` tool's generated `ui://contacts/dashboard` resource. Other clients still receive the normal launcher text instead of raw HTML. +Then try: -In the current Repl.Mcp version, MCP Apps are experimental and the UI handler returns generated HTML as a string. Future versions may add richer return types and asset helpers. +```text +contacts +contacts paged --result:page-size=5 +contact 1 +feedback demo +exit +``` -## Demo workflow +### MCP server mode -In the interactive REPL, try: +```bash +dotnet run --project samples/08-mcp-server/McpServerSample.csproj -- mcp serve +``` -- `contacts paged --result:page-size=5` to inspect the first page of a synthetic long directory -- `contacts paged --result:page-size=5 --result:cursor=5` to continue from the next cursor -- `feedback demo` to emit a successful sequence with normal, indeterminate, and warning progress states -- `feedback fail` to emit warning and error progress, then finish with a problem result -- `import contacts.csv` to see the realistic workflow that uses sampling and elicitation when the connected client supports them +This starts a stdio MCP server for the sample app. It waits for an MCP client to connect over stdin/stdout. + +### Test with MCP Inspector + +```bash +npx @modelcontextprotocol/inspector dotnet run --project samples/08-mcp-server/McpServerSample.csproj -- mcp serve +``` In MCP Inspector: @@ -65,31 +97,133 @@ In MCP Inspector: The deterministic `feedback_*` tools make it easy to verify the host's notification rendering without depending on a real CSV file. -## Agent configuration +Clients with MCP Apps support render the `contacts dashboard` tool's generated `ui://contacts/dashboard` resource. Other clients still receive the normal launcher text instead of raw HTML. + +In the current Repl.Mcp version, MCP Apps are experimental and the UI handler returns generated HTML as a string. Future versions may add richer return types and asset helpers. + +## Agent host configuration + +Use an absolute project path in agent-host config. Most hosts launch MCP servers outside your shell's current working directory, so relative paths are fragile. + +Replace `/absolute/path/to/repl` with your local clone path. -### Claude Desktop +### Generic MCP client / Claude Desktop style ```json { "mcpServers": { - "contacts": { + "repl-contacts-sample": { "command": "dotnet", - "args": ["run", "--project", "samples/08-mcp-server", "--", "mcp", "serve"] + "args": [ + "run", + "--project", + "/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj", + "--", + "mcp", + "serve" + ] } } } ``` -### VS Code (GitHub Copilot) +A copyable file lives at [`configs/generic-mcp-client.json`](configs/generic-mcp-client.json). + +### Cursor + +Project config path: `.cursor/mcp.json`. + +```json +{ + "mcpServers": { + "repl-contacts-sample": { + "command": "dotnet", + "args": [ + "run", + "--project", + "/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj", + "--", + "mcp", + "serve" + ] + } + } +} +``` + +A copyable file lives at [`configs/cursor.mcp.json`](configs/cursor.mcp.json). + +### VS Code / GitHub Copilot + +Workspace config path: `.vscode/mcp.json`. ```json { "servers": { - "contacts": { + "repl-contacts-sample": { "type": "stdio", "command": "dotnet", - "args": ["run", "--project", "samples/08-mcp-server", "--", "mcp", "serve"] + "args": [ + "run", + "--project", + "/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj", + "--", + "mcp", + "serve" + ] } } } ``` + +A copyable file lives at [`configs/vscode.mcp.json`](configs/vscode.mcp.json). + +VS Code also supports adding MCP servers from the command line: + +```bash +code --add-mcp '{"name":"repl-contacts-sample","command":"dotnet","args":["run","--project","/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj","--","mcp","serve"]}' +``` + +### Claude Code + +If your Claude Code version supports command-line MCP registration, add the sample like this: + +```bash +claude mcp add repl-contacts-sample -- dotnet run --project /absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj -- mcp serve +``` + +Otherwise, use the generic `mcpServers` JSON shape above in the relevant Claude Code project or user settings. + +### Cline + +Use Cline's MCP settings or marketplace flow to add a local stdio server with: + +- command: `dotnet` +- args: `run`, `--project`, `/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj`, `--`, `mcp`, `serve` + +If your Cline version asks for JSON, start from the generic `mcpServers` block above. + +## Adapting this sample to your app + +1. Keep your command handlers small, typed, and dependency-injected. +2. Return JSON-friendly objects instead of prose-only console output. +3. Add `app.UseMcpServer()` to register the hidden `mcp serve` command. +4. Annotate commands that agents can call: + - `.ReadOnly()` for safe queries; + - `.Destructive()` for mutations that need confirmation; + - `.Idempotent()` for operations safe to retry; + - `.OpenWorld()` for external systems; + - `.LongRunning()` for slow work; + - `.AutomationHidden()` for interactive-only or unsafe commands. +5. Document the exact MCP command and args your users should paste into their agent host. + +## Safety note + +Local MCP servers run commands on the user's machine. Only configure MCP servers from trusted repositories, review the command and arguments before starting them, and avoid hardcoding secrets in MCP config files. Prefer environment variables or host-supported secret inputs for API keys. + +## References + +- [MCP Server Integration](../../docs/mcp-overview.md) +- [MCP Server Reference](../../docs/mcp-reference.md) +- [MCP agent capabilities](../../docs/mcp-agent-capabilities.md) +- [MCP transports](../../docs/mcp-transports.md) diff --git a/samples/08-mcp-server/configs/cursor.mcp.json b/samples/08-mcp-server/configs/cursor.mcp.json new file mode 100644 index 0000000..27ff033 --- /dev/null +++ b/samples/08-mcp-server/configs/cursor.mcp.json @@ -0,0 +1,15 @@ +{ + "mcpServers": { + "repl-contacts-sample": { + "command": "dotnet", + "args": [ + "run", + "--project", + "/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj", + "--", + "mcp", + "serve" + ] + } + } +} diff --git a/samples/08-mcp-server/configs/generic-mcp-client.json b/samples/08-mcp-server/configs/generic-mcp-client.json new file mode 100644 index 0000000..27ff033 --- /dev/null +++ b/samples/08-mcp-server/configs/generic-mcp-client.json @@ -0,0 +1,15 @@ +{ + "mcpServers": { + "repl-contacts-sample": { + "command": "dotnet", + "args": [ + "run", + "--project", + "/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj", + "--", + "mcp", + "serve" + ] + } + } +} diff --git a/samples/08-mcp-server/configs/vscode.mcp.json b/samples/08-mcp-server/configs/vscode.mcp.json new file mode 100644 index 0000000..a7c4564 --- /dev/null +++ b/samples/08-mcp-server/configs/vscode.mcp.json @@ -0,0 +1,16 @@ +{ + "servers": { + "repl-contacts-sample": { + "type": "stdio", + "command": "dotnet", + "args": [ + "run", + "--project", + "/absolute/path/to/repl/samples/08-mcp-server/McpServerSample.csproj", + "--", + "mcp", + "serve" + ] + } + } +} diff --git a/samples/README.md b/samples/README.md index 0363665..159c2c6 100644 --- a/samples/README.md +++ b/samples/README.md @@ -20,8 +20,8 @@ If you’re new, start with **01**, then follow the sequence. `Repl.Testing` harness: multi-step + multi-session, typed results, interaction/timeline events, metadata snapshots. 7. [07 — Spectre](07-spectre/) `Repl.Spectre` integration: FigletText, Table, paged result tables, Panel, Tree, BarChart, BreakdownChart, Calendar, JsonText, TextPath, Grid, Columns, Rule, Status, Progress, and all Spectre-powered prompts. -8. [08 — MCP Server](08-mcp-server/) - MCP server mode: tools, paged structured results, resources, prompts, behavioral annotations, automation visibility, and a minimal MCP Apps UI. +8. [08 — Build an MCP Server with Repl.Mcp](08-mcp-server/) + Build a concrete MCP server from a Repl command graph: CLI + REPL + MCP mode, host config snippets for Cursor/VS Code/Claude/Cline, tools, resources, prompts, behavioral annotations, automation visibility, and a minimal MCP Apps UI. ## Run