Skip to content

Commit 5885914

Browse files
tadasantclaude
andcommitted
fix: Separate Package and Remote transport contexts for URL templating
Address breaking change feedback by creating separate transport types: - Package transports: reference parent arguments/environment variables - Remote transports: define their own variables object Key changes: - Revert base Transport schema - keep original Package behavior unchanged - Add RemoteStreamableHttpTransport and RemoteSseTransport via allOf pattern - Create separate RemoteTransport Go type with Variables field - Update API types to use RemoteTransport for remotes array - Fix validation logic for both contexts - Update test files to use correct types This maintains backwards compatibility for Package context while enabling the needed templating functionality for Remote context. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 286af5c commit 5885914

File tree

8 files changed

+94
-52
lines changed

8 files changed

+94
-52
lines changed

docs/reference/server-json/generic-server-json.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ For MCP servers that follow a custom installation path or are embedded in applic
672672

673673
### Remote Server with URL Templating
674674

675-
This example demonstrates URL templating for remote servers, useful for multi-tenant deployments where each instance has its own endpoint:
675+
This example demonstrates URL templating for remote servers, useful for multi-tenant deployments where each instance has its own endpoint. Unlike Package transports (which reference parent arguments/environment variables), Remote transports define their own variables:
676676

677677
```json
678678
{

docs/reference/server-json/server.schema.json

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@
377377
},
378378
"url": {
379379
"type": "string",
380-
"description": "URL template for the streamable-http transport. Variables in {curly_braces} reference variable names from the 'variables' object. If variables are not provided, {curly_braces} should be treated as literal text. After variable substitution, this should produce a valid URI.",
380+
"description": "URL template for the streamable-http transport. Variables in {curly_braces} can reference argument valueHints, argument names, or environment variable names from the parent Package context. After variable substitution, this should produce a valid URI.",
381381
"example": "https://api.example.com/mcp"
382382
},
383383
"headers": {
@@ -386,13 +386,6 @@
386386
"items": {
387387
"$ref": "#/definitions/KeyValueInput"
388388
}
389-
},
390-
"variables": {
391-
"type": "object",
392-
"description": "Configuration variables that can be referenced in URL template {curly_braces}. The key is the variable name, and the value defines the variable properties.",
393-
"additionalProperties": {
394-
"$ref": "#/definitions/Input"
395-
}
396389
}
397390
}
398391
},
@@ -414,7 +407,7 @@
414407
"url": {
415408
"type": "string",
416409
"format": "uri",
417-
"description": "Server-Sent Events endpoint URL template. Variables in {curly_braces} reference variable names from the 'variables' object. If variables are not provided, {curly_braces} should be treated as literal text. After variable substitution, this should produce a valid URI.",
410+
"description": "Server-Sent Events endpoint URL template. Variables in {curly_braces} can reference argument valueHints, argument names, or environment variable names from the parent Package context. After variable substitution, this should produce a valid URI.",
418411
"example": "https://mcp-fs.example.com/sse"
419412
},
420413
"headers": {
@@ -423,15 +416,57 @@
423416
"items": {
424417
"$ref": "#/definitions/KeyValueInput"
425418
}
419+
}
420+
}
421+
},
422+
"RemoteStreamableHttpTransport": {
423+
"allOf": [
424+
{
425+
"$ref": "#/definitions/StreamableHttpTransport"
426426
},
427-
"variables": {
427+
{
428428
"type": "object",
429-
"description": "Configuration variables that can be referenced in URL template {curly_braces}. The key is the variable name, and the value defines the variable properties.",
430-
"additionalProperties": {
431-
"$ref": "#/definitions/Input"
429+
"properties": {
430+
"url": {
431+
"type": "string",
432+
"description": "URL template for the streamable-http transport. Variables in {curly_braces} reference variable names from the 'variables' object. If variables are not provided, {curly_braces} should be treated as literal text. After variable substitution, this should produce a valid URI.",
433+
"example": "https://api.example.com/mcp/{tenant_id}"
434+
},
435+
"variables": {
436+
"type": "object",
437+
"description": "Configuration variables that can be referenced in URL template {curly_braces}. The key is the variable name, and the value defines the variable properties.",
438+
"additionalProperties": {
439+
"$ref": "#/definitions/Input"
440+
}
441+
}
432442
}
433443
}
434-
}
444+
]
445+
},
446+
"RemoteSseTransport": {
447+
"allOf": [
448+
{
449+
"$ref": "#/definitions/SseTransport"
450+
},
451+
{
452+
"type": "object",
453+
"properties": {
454+
"url": {
455+
"type": "string",
456+
"format": "uri",
457+
"description": "Server-Sent Events endpoint URL template. Variables in {curly_braces} reference variable names from the 'variables' object. If variables are not provided, {curly_braces} should be treated as literal text. After variable substitution, this should produce a valid URI.",
458+
"example": "https://mcp-fs.example.com/sse/{tenant_id}"
459+
},
460+
"variables": {
461+
"type": "object",
462+
"description": "Configuration variables that can be referenced in URL template {curly_braces}. The key is the variable name, and the value defines the variable properties.",
463+
"additionalProperties": {
464+
"$ref": "#/definitions/Input"
465+
}
466+
}
467+
}
468+
}
469+
]
435470
},
436471
"ServerDetail": {
437472
"description": "Schema for a static representation of an MCP server. Used in various contexts related to discovery, installation, and configuration.",
@@ -459,10 +494,10 @@
459494
"items": {
460495
"anyOf": [
461496
{
462-
"$ref": "#/definitions/StreamableHttpTransport"
497+
"$ref": "#/definitions/RemoteStreamableHttpTransport"
463498
},
464499
{
465-
"$ref": "#/definitions/SseTransport"
500+
"$ref": "#/definitions/RemoteSseTransport"
466501
}
467502
]
468503
}

internal/api/handlers/v0/publish_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ func TestPublishEndpoint(t *testing.T) {
335335
},
336336
},
337337
},
338-
Remotes: []model.Transport{
338+
Remotes: []model.RemoteTransport{
339339
{
340340
Type: model.TransportTypeStreamableHTTP,
341341
URL: "https://example.com/api",

internal/service/registry_service_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func TestValidateNoDuplicateRemoteURLs(t *testing.T) {
2121
Name: "com.example/existing-server",
2222
Description: "An existing server",
2323
Version: "1.0.0",
24-
Remotes: []model.Transport{
24+
Remotes: []model.RemoteTransport{
2525
{Type: "streamable-http", URL: "https://api.example.com/mcp"},
2626
{Type: "sse", URL: "https://webhook.example.com/sse"},
2727
},
@@ -30,7 +30,7 @@ func TestValidateNoDuplicateRemoteURLs(t *testing.T) {
3030
Name: "com.microsoft/another-server",
3131
Description: "Another existing server",
3232
Version: "1.0.0",
33-
Remotes: []model.Transport{
33+
Remotes: []model.RemoteTransport{
3434
{Type: "streamable-http", URL: "https://api.microsoft.com/mcp"},
3535
},
3636
},
@@ -58,7 +58,7 @@ func TestValidateNoDuplicateRemoteURLs(t *testing.T) {
5858
Name: "com.example/new-server",
5959
Description: "A new server with no remotes",
6060
Version: "1.0.0",
61-
Remotes: []model.Transport{},
61+
Remotes: []model.RemoteTransport{},
6262
},
6363
expectError: false,
6464
},
@@ -68,7 +68,7 @@ func TestValidateNoDuplicateRemoteURLs(t *testing.T) {
6868
Name: "com.example/new-server",
6969
Description: "A new server",
7070
Version: "1.0.0",
71-
Remotes: []model.Transport{
71+
Remotes: []model.RemoteTransport{
7272
{Type: "streamable-http", URL: "https://new.example.com/mcp"},
7373
{Type: "sse", URL: "https://unique.example.com/sse"},
7474
},
@@ -81,7 +81,7 @@ func TestValidateNoDuplicateRemoteURLs(t *testing.T) {
8181
Name: "com.example/new-server",
8282
Description: "A new server with duplicate URL",
8383
Version: "1.0.0",
84-
Remotes: []model.Transport{
84+
Remotes: []model.RemoteTransport{
8585
{Type: "streamable-http", URL: "https://api.example.com/mcp"}, // This URL already exists
8686
},
8787
},
@@ -94,7 +94,7 @@ func TestValidateNoDuplicateRemoteURLs(t *testing.T) {
9494
Name: "com.example/existing-server", // Same name as existing
9595
Description: "Updated existing server",
9696
Version: "1.1.0",
97-
Remotes: []model.Transport{
97+
Remotes: []model.RemoteTransport{
9898
{Type: "streamable-http", URL: "https://api.example.com/mcp"}, // Same URL as before
9999
},
100100
},

internal/validators/validators.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ func collectAvailableVariables(pkg *model.Package) []string {
293293
}
294294

295295
// collectRemoteTransportVariables extracts available variable names from a remote transport
296-
func collectRemoteTransportVariables(transport *model.Transport) []string {
296+
func collectRemoteTransportVariables(transport *model.RemoteTransport) []string {
297297
var variables []string
298298

299299
// Add variable names from the Variables map
@@ -338,7 +338,7 @@ func validatePackageTransport(transport *model.Transport, availableVariables []s
338338
}
339339

340340
// validateRemoteTransport validates a remote transport with optional templating
341-
func validateRemoteTransport(obj *model.Transport) error {
341+
func validateRemoteTransport(obj *model.RemoteTransport) error {
342342
// Validate transport type is supported - remotes only support streamable-http and sse
343343
switch obj.Type {
344344
case model.TransportTypeStreamableHTTP, model.TransportTypeSSE:

0 commit comments

Comments
 (0)