# MCP Tools Plugin Discovery Version

This version demonstrates a scalable version of the JSON-RPC/MCP-style sample.

The host project no longer lists every tool project manually in `Program.cs`.

Instead, startup contains only:

```csharp
builder.Services.AddMcpTools(builder.Configuration);
```

The plugin folder is configured in `JsonRpcEndpointSample/appsettings.json`:

```json
{
  "McpTools": {
    "PluginFolder": "Modules"
  }
}
```

At runtime, `AddMcpTools`:

1. Reads the plugin folder from configuration.
2. Loads `*.dll` files from that folder.
3. Keeps only assemblies decorated with `[assembly: RpcAssembly]`.
4. Scans those assemblies for classes decorated with `[RpcMethod]`.
5. Registers all RPC handlers in DI as keyed services.
6. Automatically builds `/rpc/methods` metadata for all RPC methods.
7. Builds `/rpc/tools` and MCP `tools/list` metadata only for handlers also decorated with `[ExposeAsMcpTool]`.
8. Automatically generates input/output JSON schemas from request/response DTOs for exposed MCP tools.

## Assembly-level marker

Each tool module declares itself once:

```csharp
using JsonRpcEndpointSample.Rpc.Abstractions;

[assembly: RpcAssembly("Bank")]
```

## Handler-level declaration

Each handler declares its RPC method:

```csharp
[RpcMethod(
    "Bank.MakeDeposit",
    Description = "Deposits money into an existing bank account and returns the new balance.",
    IsReadOnly = false)]
[ExposeAsMcpTool]
public sealed class BankMakeDepositHandler
    : RpcRequestHandler<MakeDepositRequest, MakeDepositResponse>
{
}
```

## DTO property descriptions

Request/response DTO properties can describe themselves:

```csharp
[RpcSchemaProperty("Bank account number receiving the deposit.")]
public string AccountNumber { get; set; } = string.Empty;
```

## Build behavior in the demo

The host project has project references to Bank and Shipment with:

```xml
ReferenceOutputAssembly="false"
OutputItemType="McpPlugin"
```

This means the host project builds those projects and copies their output DLLs into:

```text
bin/Debug/net9.0/Modules
```

but the host code does not directly reference Bank or Shipment types.

That keeps `Program.cs` stable even when many tool modules exist.

## Test endpoints

After running the app, open Swagger:

```text
http://localhost:<port>/swagger
```

Or test from PowerShell:

```powershell
Invoke-RestMethod -Uri "http://localhost:<port>/rpc/methods" -Method Get
```

```powershell
Invoke-RestMethod -Uri "http://localhost:<port>/mcp" -Method Post -ContentType "application/json" -Body '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":"2"}'
```

```powershell
Invoke-RestMethod -Uri "http://localhost:<port>/mcp" -Method Post -ContentType "application/json" -Body '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"Bank.MakeDeposit","arguments":{"accountNumber":"A-100","amount":250}},"id":"3"}'
```


## MCP exposure is opt-in

`[RpcMethod]` registers a handler for the `/rpc` endpoint.

`[ExposeAsMcpTool]` additionally exposes that handler through the MCP `tools/list` and `tools/call` surface.

This allows internal or application-only RPC methods to remain callable through `/rpc` while staying hidden from MCP clients.
