{
"mcpSets": {
"developer-tools": {
"host": "mcp.example.com",
"endpoint": "/developer-tools",
"resource": "https://mcp.example.com/developer-tools",
"scope": "mcp-tools",
"identity": { "roles": ["developer"] },
"members": [
{ "service": "github", "path": "/github",
"tools": ["list_repos", "get_repo"] },
{ "service": "metrics", "path": "/metrics" }
]
}
},
"routes": [
{
"host": "mcp.example.com",
"path": "/github",
"backend": "https://api.github.com",
"auth": {},
"upstream": { "tokenBroker": { "provider": "github" } },
"openapi": { "url": "http://landing/github-openapi.json", "public": false },
"mcp": {
"enabled": true,
"name": "github",
"standalone": false,
"operations": [
{ "name": "list_repos", "operationId": "list_repos" },
{ "name": "get_repo", "operationId": "get_repo" },
{ "name": "list_issues", "operationId": "list_issues" }
]
}
},
{
"host": "mcp.example.com",
"path": "/metrics",
"backend": "http://metrics-mcp:8080",
"auth": {},
"mcp": {
"enabled": true,
"name": "metrics",
"standalone": false,
"upstream": {
"url": "http://metrics-mcp:8080/mcp",
"tools": { "include": ["list_*", "get_*"], "exclude": ["*_secret"] }
}
}
}
]
}MCP tools
This example builds one MCP surface from three sources: a documented REST API (derived into tools), an existing MCP server (proxied) and an aggregating set that groups both under one endpoint with its own audience, scope and identity.
File
Abridged (the authProviders and tokenBroker blocks are omitted here;
they are in the file):
How it fits together
github is a REST-derived service:
mcp.operationsnames three tools,openapiresolves their method, path, parameters and body.metrics is a proxied MCP server:
mcp.upstream.urlforwards to it, andtoolskeeps onlylist_*/get_*(never*_secret).Both declare
standalone: false, so they are reachable only through the set.developer-tools aggregates them at
https://mcp.example.com/developer-tools; the set enforces thedeveloperrole, the audience and themcp-toolsscope, and limits the github member to two tools.
The github tools call
https://api.github.comwith the caller’s delegated token from the token broker, never the Gate One bearer.
Try it
# The set advertises its own protected-resource metadata.
curl -s https://mcp.example.com/developer-tools/.well-known/oauth-protected-resource | jq
# List the aggregated tools, then call one.
curl -s https://mcp.example.com/developer-tools \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
curl -s https://mcp.example.com/developer-tools \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"list_repos","arguments":{}}}'The github tools answer with a connect_url until the user connects
GitHub on the connections page; the metrics tools need no per-user
credential.
Note |
|