Skip to content

Commit 53dc50c

Browse files
authored
Tool proxy (#40)
Add tool proxy service update README with the new functionality
1 parent 445bdb0 commit 53dc50c

19 files changed

+1402
-34
lines changed

.github/workflows/image.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@ jobs:
3434
- name: Restore dependencies
3535
run: dotnet restore dotnet/Microsoft.McpGateway.sln --runtime linux-x64
3636

37-
- name: Publish and push the container image
38-
run: dotnet publish dotnet/Microsoft.McpGateway.Service/src/Microsoft.McpGateway.Service.csproj --configuration Release --no-restore /p:PublishProfile=github.pubxml /p:ContainerRepository=${{ github.repository }}
37+
- name: Publish and push the mcp-gateway container image
38+
run: dotnet publish dotnet/Microsoft.McpGateway.Service/src/Microsoft.McpGateway.Service.csproj --configuration Release --no-restore /p:PublishProfile=github.pubxml /p:ContainerRepository=${{ github.repository_owner }}/mcp-gateway
39+
40+
- name: Publish and push the tool-gateway container image
41+
run: dotnet publish dotnet/Microsoft.McpGateway.Tools/src/Microsoft.McpGateway.Tools.csproj --configuration Release --no-restore /p:PublishProfile=github.pubxml /p:ContainerRepository=${{ github.repository_owner }}/tool-gateway

README.md

Lines changed: 275 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,52 +25,103 @@ This project provides:
2525

2626
- **MCP Server**: A server implementing the Model Context Protocol, which typically a streamable HTTP endpoint.
2727
- **Adapters**: Logical resources representing MCP servers in the gateway, managed under the `/adapters` scope. Designed to coexist with other resource types (e.g., `/agents`) in a unified AI development platform.
28+
- **Tools**: Registered resources with MCP tool definitions that can be dynamically routed via the tool gateway router. Each tool includes metadata about its execution endpoint and input schema.
29+
- **Tool Gateway Router**: An MCP server that acts as an intelligent router, directing tool execution requests to the appropriate registered tool servers based on tool definitions. Multiple router instances may run behind the gateway for session affinity.
2830
- **Session-Aware Stateful Routing**: Ensures that all requests with a given `session_id` are consistently routed to the same MCP server instance.
2931

3032
## Architecture
3133

3234
```mermaid
3335
flowchart LR
34-
subgraph Clients["Clients"]
35-
DataClient["Agent/MCP Data<br>Client"]
36-
MgmtClient["Server Management<br>Client"]
37-
end
38-
39-
subgraph DataPlane["Data Plane"]
40-
Routing["Distributed Routing"]
41-
end
42-
43-
subgraph ControlPlane["Control Plane"]
44-
DeploymentManagement["Deployment Management"]
45-
MetadataManagement["Metadata Management"]
36+
subgraph Clients[" "]
37+
direction TB
38+
DataClient["🔌 Agent/MCP<br>Data Client"]
39+
MgmtClient["⚙️ Management<br>Client"]
4640
end
4741
4842
subgraph Gateway["MCP Gateway"]
49-
Auth["AuthN - Bearer<br>AuthZ - RBAC/ACL"]
50-
Auth2["AuthN - Bearer<br>AuthZ - RBAC/ACL"]
51-
DataPlane
52-
ControlPlane
43+
direction TB
44+
45+
subgraph Auth1["Authentication & Authorization"]
46+
Auth["🔐 Data Plane Auth<br>Bearer Token / RBAC"]
47+
Auth2["🔐 Control Plane Auth<br>Bearer Token / RBAC"]
48+
end
49+
50+
subgraph DataPlane["Data Plane"]
51+
Routing["🔀 Adapter Routing<br>/adapters/{name}/mcp"]
52+
ToolRouting["🔀 Tool Router Gateway<br>/mcp"]
53+
end
54+
55+
subgraph ControlPlane["Control Plane"]
56+
direction LR
57+
AdapterMgmt["📦 Adapter Management<br>/adapters CRUD"]
58+
ToolMgmt["🔧 Tool Management<br>/tools CRUD"]
59+
end
60+
61+
subgraph Management["Backend Services"]
62+
DeploymentMgmt["☸️ Deployment Manager"]
63+
MetadataMgmt["📋 Metadata Manager"]
64+
end
5365
end
5466
5567
subgraph Cluster["Kubernetes Cluster"]
56-
PodA["Server Pod<br>mcp-a-0"]
57-
PodA1["Server Pod<br>mcp-a-1"]
58-
PodB["Server Pod<br>mcp-b-0"]
68+
direction TB
69+
70+
subgraph ServerRow[" "]
71+
direction LR
72+
73+
subgraph MCPServers["MCP Servers"]
74+
direction TB
75+
PodA["mcp-a-0"]
76+
PodA1["mcp-a-1"]
77+
PodB["mcp-b-0"]
78+
end
79+
80+
subgraph ToolRouters["Tool Gateway Routers"]
81+
direction TB
82+
Router1["toolgateway-0"]
83+
Router2["toolgateway-1"]
84+
end
85+
end
86+
87+
subgraph ToolServers["Registered Tool Servers"]
88+
direction LR
89+
Tool1["tool-1-0"]
90+
Tool2["tool-2-0"]
91+
end
5992
end
6093
61-
DataClient -- SSE/<br>Streamable HTTP --> Auth
62-
MgmtClient -- "CRUD /adapters" --> Auth2 --> ControlPlane
94+
Metadata[("💾 Metadata Store<br>Server & Tool Info")]
95+
96+
DataClient -->|"MCP Requests"| Auth
97+
MgmtClient -->|"API Calls"| Auth2
98+
6399
Auth --> Routing
64-
Routing -- Session Affinity Routing --> PodA
65-
Routing --> PodA1 & PodB
66-
MetadataManagement --> Metadata[("Server<br>Metadata")]
67-
DeploymentManagement -- "Deployment/Status Check"--> Cluster
100+
Auth --> ToolRouting
101+
Auth2 --> AdapterMgmt
102+
Auth2 --> ToolMgmt
103+
104+
AdapterMgmt & ToolMgmt --> DeploymentMgmt
105+
AdapterMgmt & ToolMgmt --> MetadataMgmt
106+
107+
Routing -.->|"Session Affinity"| MCPServers
108+
ToolRouting -.->|"Session Affinity"| ToolRouters
109+
ToolRouters ==>|"Dynamic Routing"| ToolServers
110+
111+
DeploymentMgmt -->|"Deploy & Monitor"| Cluster
112+
MetadataMgmt <-->|"Read/Write"| Metadata
113+
114+
style Gateway fill:#e1f5ff
115+
style Cluster fill:#fff4e1
116+
style Metadata fill:#f0f0f0
68117
```
69118

70119
## Features
71120

72121
### Control Plane – RESTful APIs for MCP Server Management
73122

123+
#### MCP Server Management (Adapters)
124+
74125
- `POST /adapters` — Deploy and register a new MCP server.
75126
- `GET /adapters` — List all MCP servers the user can access.
76127
- `GET /adapters/{name}` — Retrieve metadata for a specific adapter.
@@ -79,16 +130,56 @@ flowchart LR
79130
- `PUT /adapters/{name}` — Update the deployment.
80131
- `DELETE /adapters/{name}` — Remove the server.
81132

133+
#### Tool Registration and Management
134+
135+
- `POST /tools` — Register and deploy a tool with MCP tool definition metadata.
136+
- `GET /tools` — List all registered tools the user can access.
137+
- `GET /tools/{name}` — Retrieve metadata and tool definition for a specific tool.
138+
- `GET /tools/{name}/status` — Check the tool deployment status.
139+
- `GET /tools/{name}/logs` — Access the tool server's running logs.
140+
- `PUT /tools/{name}` — Update a tool deployment and definition.
141+
- `DELETE /tools/{name}` — Remove a registered tool.
142+
82143
### Data Plane – Gateway Routing for MCP Servers
83144

145+
#### Direct MCP Server Access
146+
84147
- `POST /adapters/{name}/mcp` — Establish a streamable HTTP connection.
85148

149+
#### Dynamic Tool Routing via Tool Gateway Router
150+
151+
- `POST /mcp` — Route requests to the tool gateway router, which dynamically routes to registered tools based on tool definitions. The router itself is an MCP server with multiple instances hosted behind the gateway for scalability.
152+
86153
### Additional Capabilities
87154

88155
- Authentication and authorization support (production mode).
89156
- Stateless reverse proxy with a distributed session store (production mode).
90157
- Kubernetes-native deployment using StatefulSets and headless services.
91158

159+
### Tool Registration and Dynamic Routing
160+
161+
The MCP Gateway now supports **tool registration** with dynamic routing capabilities, enabling a scalable architecture for managing and executing MCP tools.
162+
163+
### How It Works
164+
165+
1. **Tool Registration**: Developers register tools via the `/tools` API endpoint, providing:
166+
- Container image details (name and version)
167+
- MCP tool definition (name, description, input schema)
168+
- Execution endpoint configuration (port and path)
169+
- Deployment configuration (replicas, environment variables)
170+
171+
2. **Tool Gateway Router**: A specialized MCP server that acts as an intelligent router:
172+
- Runs as multiple instances behind the gateway for high availability
173+
- Maintains awareness of all registered tools and their definitions
174+
- Dynamically routes tool execution requests to the appropriate tool server
175+
- Accessed via `POST /mcp` endpoint (without adapter name)
176+
177+
3. **Dynamic Routing**: When clients send MCP requests to `/mcp`:
178+
- The gateway routes requests to available tool gateway router instances with session affinity
179+
- The router analyzes the tool call in the request
180+
- Based on the tool definition, it forwards the execution to the correct registered tool server
181+
- Results are returned through the router back to the client
182+
92183
## Getting Started - Local Deployment
93184

94185
### 1. Prepare Local Development Environment
@@ -108,14 +199,19 @@ docker build -f mcp-example-server/Dockerfile mcp-example-server -t localhost:50
108199
docker push localhost:5000/mcp-example:1.0.0
109200
```
110201

111-
### 4. Build & Publish MCP Gateway
202+
### 4. Build & Publish MCP Gateway and Tool Gateway Router
112203
(Optional) Open `dotnet/Microsoft.McpGateway.sln` with Visual Studio.
113204

114-
Publish the MCP Gateway image by right-clicking `Publish` on `Microsoft.McpGateway.Service` in Visual Studio, or run:
205+
Publish the MCP Gateway image:
115206
```sh
116207
dotnet publish dotnet/Microsoft.McpGateway.Service/src/Microsoft.McpGateway.Service.csproj -c Release /p:PublishProfile=localhost_5000.pubxml
117208
```
118209

210+
Publish the Tool Gateway Router image:
211+
```sh
212+
dotnet publish dotnet/Microsoft.McpGateway.Tools/src/Microsoft.McpGateway.Tools.csproj -c Release /p:PublishProfile=localhost_5000.pubxml
213+
```
214+
119215
### 5. Deploy MCP Gateway to Kubernetes Cluster
120216
Apply the deployment manifests:
121217
```sh
@@ -166,7 +262,76 @@ kubectl port-forward -n adapter svc/mcpgateway-service 8000:8000
166262
- For other servers:
167263
- `http://localhost:8000/adapters/{name}/mcp` (Streamable HTTP)
168264

169-
### 9. Clean the Environment
265+
### 9. Test Tool Registration and Dynamic Routing
266+
267+
#### Build & Publish a Tool Server Image
268+
269+
First, build and push a tool server image to your local registry:
270+
```sh
271+
docker build -f sample-tool-server/Dockerfile sample-tool-server -t localhost:5000/weather-tool:1.0.0
272+
docker push localhost:5000/weather-tool:1.0.0
273+
```
274+
275+
#### Register a Tool
276+
277+
Send a request to register a tool with its definition:
278+
```http
279+
POST http://localhost:8000/tools
280+
Content-Type: application/json
281+
```
282+
```json
283+
{
284+
"name": "weather",
285+
"imageName": "weather-tool",
286+
"imageVersion": "1.0.0",
287+
"description": "Weather tool for getting current weather information",
288+
"toolDefinition": {
289+
"tool": {
290+
"name": "weather",
291+
"title": "Weather Information",
292+
"description": "Gets the current weather for a specified location.",
293+
"type": "http",
294+
"inputSchema": {
295+
"type": "object",
296+
"properties": {
297+
"location": {
298+
"type": "string",
299+
"description": "The city and state, e.g. San Francisco, CA"
300+
}
301+
},
302+
"required": ["location"]
303+
}
304+
},
305+
"port": 8000
306+
}
307+
}
308+
```
309+
310+
#### Verify Tool Deployment
311+
312+
Check the tool deployment status:
313+
```http
314+
GET http://localhost:8000/tools/weather/status
315+
```
316+
317+
#### Test Tool Routing via Tool Gateway Router
318+
319+
Use an MCP client (like VS Code) to connect to the tool gateway router:
320+
321+
Sample `.vscode/mcp.json` that connects to the tool gateway router:
322+
```json
323+
{
324+
"servers": {
325+
"tool-gateway": {
326+
"url": "http://localhost:8000/mcp"
327+
}
328+
}
329+
}
330+
```
331+
332+
The router will automatically route tool calls to the appropriate registered tool servers based on the tool name in the MCP request.
333+
334+
### 10. Clean the Environment
170335
To remove all deployed resources, delete the Kubernetes namespace:
171336
```sh
172337
kubectl delete namespace adapter
@@ -307,15 +472,94 @@ az acr build -r "mgreg$resourceLabel" -f mcp-example-server/Dockerfile mcp-examp
307472
308473
- For other servers:
309474
- `http://<resourceLabel>.<location>.cloudapp.azure.com/adapters/{name}/mcp` (Streamable HTTP)
310-
- `http://<resourceLabel>.<location>.cloudapp.azure.com/adapters/{name}/sse` (SSE)
311475

312-
### 7. Clean the Environment
476+
### 7. Test Tool Registration and Dynamic Routing
477+
478+
#### Build & Publish a Tool Server Image
479+
480+
Build and push a tool server image to ACR:
481+
```sh
482+
az acr build -r "mgreg$resourceLabel" -f sample-tool-server/Dockerfile sample-tool-server -t "mgreg$resourceLabel.azurecr.io/weather-tool:1.0.0"
483+
```
484+
485+
#### Register a Tool
486+
487+
Acquire a bearer token:
488+
```sh
489+
az account get-access-token --resource $clientId
490+
```
491+
492+
Send a request to register a tool with its definition:
493+
```http
494+
POST http://<resourceLabel>.<location>.cloudapp.azure.com/tools
495+
Authorization: Bearer <token>
496+
Content-Type: application/json
497+
```
498+
```json
499+
{
500+
"name": "weather",
501+
"imageName": "weather-tool",
502+
"imageVersion": "1.0.0",
503+
"useWorkloadIdentity": true,
504+
"description": "Weather tool for getting current weather information",
505+
"toolDefinition": {
506+
"tool": {
507+
"name": "weather",
508+
"title": "Weather Information",
509+
"description": "Gets the current weather for a specified location.",
510+
"type": "http",
511+
"inputSchema": {
512+
"type": "object",
513+
"properties": {
514+
"location": {
515+
"type": "string",
516+
"description": "The city and state, e.g. San Francisco, CA"
517+
}
518+
},
519+
"required": ["location"]
520+
},
521+
"annotations": {
522+
"readOnly": true
523+
}
524+
},
525+
"port": 8000
526+
}
527+
}
528+
```
529+
530+
#### Verify Tool Deployment
531+
532+
Check the tool deployment status:
533+
```http
534+
GET http://<resourceLabel>.<location>.cloudapp.azure.com/tools/weather/status
535+
Authorization: Bearer <token>
536+
```
537+
538+
#### Test Tool Routing via Tool Gateway Router
539+
540+
Use an MCP client (like VS Code) to connect to the tool gateway router:
541+
542+
Sample `.vscode/mcp.json` that connects to the tool gateway router:
543+
```json
544+
{
545+
"servers": {
546+
"tool-gateway": {
547+
"url": "http://<resourceLabel>.<location>.cloudapp.azure.com/mcp"
548+
}
549+
}
550+
}
551+
```
552+
> **Note:** Authentication is required. VS Code will handle the authentication process.
553+
554+
The router will automatically route tool calls to the appropriate registered tool servers based on the tool name in the MCP request.
555+
556+
### 8. Clean the Environment
313557
To remove all deployed resources, delete the resource group from Azure portal or run:
314558
```sh
315559
az group delete --name <resourceGroupName> --yes
316560
```
317561

318-
### 8. Production Onboarding
562+
### 9. Production Onboarding
319563

320564
- **TLS Configuration**
321565
Set up HTTPS on Azure Application Gateway (AAG) listener using valid TLS certificates.

0 commit comments

Comments
 (0)