Skip to content

Structured inputs: MCP server_url template ({{server_url}}) rejected at agent create — 'not a valid URI' #47684

Description

@guramrit-dhillon

Structured inputs: MCP server_url template ({{server_url}}) rejected at agent create — format: '{{server_url}}' is not a valid URI

Description

Following Customize agent behavior at runtime with structured inputs → Use structured inputs with MCP servers, creating a prompt agent whose MCP tool puts a handlebar template in server_url is rejected at create-version time. The server_url is validated as a strict URI before structured-input substitution, so the documented placeholder can never be stored.

Repro (the doc's example)

# azure-ai-projects==2.2.0, openai==2.44.0
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MCPTool, PromptAgentDefinition, StructuredInputDefinition
from azure.identity import DefaultAzureCredential

project = AIProjectClient(
    endpoint="https://<resource>.services.ai.azure.com/api/projects/<project>",
    credential=DefaultAzureCredential(),
)

tool = MCPTool(server_label="{{server_label}}", server_url="{{server_url}}", require_approval="never")

project.agents.create_version(
    agent_name="mcp-dynamic-agent",
    definition=PromptAgentDefinition(
        model="gpt-4o-mini",
        instructions="You are a helpful assistant.",
        tools=[tool],
        structured_inputs={
            "server_label": StructuredInputDefinition(description="MCP server label", required=True, schema={"type": "string"}),
            "server_url":   StructuredInputDefinition(description="MCP server URL",   required=True, schema={"type": "string"}),
        },
    ),
)

Result:

azure.core.exceptions.HttpResponseError: (invalid_payload)
  format: '{{server_url}}' is not a valid URI
  param: /definition/tools/0/server_url

Equivalent raw REST (POST {endpoint}/agents/<name>/versions?api-version=v1, body {"definition": {...}}) returns the same 400.

The failure is specific to server_url

Templating works for the other MCP fields in the same example — only server_url is URI-validated. With a static server_url, the identical definition creates successfully and the templates are stored verbatim:

// POST .../agents?api-version=v1  -> 200 OK; GET shows the stored definition:
"tools": [{
  "type": "mcp",
  "server_label": "{{server_label}}",                  // <- stored literally (OK)
  "server_url":   "https://gitmcp.io/org/repo",         // <- must be a real URI
  "headers":      { "Authorization": "{{auth_token}}" } // <- stored literally (OK)
}]

So the substitution engine accepts templates in server_label and headers; the issue is isolated to the URI-format validation on server_url.

If the template is instead embedded in an otherwise-valid path ("https://host/{{segment}}"), create succeeds but the braces are percent-encoded at store time → the stored value becomes https://host/%7B%7Bsegment%7D%7D, so runtime substitution never matches and the MCP client connects to the literal encoded URL.

Expected

server_url should accept a handlebar template (skipping URI-format validation/normalization when the value is a template), consistent with server_label/headers and with the documentation, and substitute it from the request-body structured_inputs at POST /openai/v1/responses.

Environment

  • azure-ai-projects==2.2.0, openai==2.44.0, api-version=v1 (also reproduced on 2025-11-15-preview).
  • Reproduced via the Python SDK and raw REST, on multiple Foundry resources across different regions/tenants.

Ask

Relax server_url (and confirm server_label) URI-format validation for handlebar templates so the documented MCP structured-input pattern works — or, if the feature is not yet enabled in these regions, please annotate the docs and advise how to opt in.

Metadata

Metadata

Assignees

No one assigned

    Labels

    customer-reportedIssues that are reported by GitHub users external to the Azure organization.needs-triageWorkflow: This is a new issue that needs to be triaged to the appropriate team.questionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions