Azure / Azure/azure-dev

Emit MCP-related information when deploying code to a MCP function app

Open
#6,043 0 comments 0 reactions 0 assignees View on GitHub
area/functions area/mcp enhancement
Dominant language
Go
Stars
569
Forks
364
Avg merge
2d 19h
Merged PRs (30d)
136

Description

## 1. Background

**Goal**: minimize the friction to add a custom MCP tool hosted on Functions to your agent.

**Problem**: developers must know to construct the remote MCP endpoint themselves, get the authentication information, and know where to go to supply this information to their agent.

> [!NOTE]
> This is a point-in-time optimization until we can declaratively add MCP tools hosted on Functions to agents.

## 2. Ideal user journey

1. Developer initializes MCP function app project: e.g., `azd init --template python-mcp-sdk-functions-azd`
2. Developer modifies sample code and tests locally
3. Developer runs `azd up` to deploy MCP server to Azure
**a. Terminal returns information to help the next step.**
4. Developer manually adds the MCP tool to their Foundry agent, inputting information copied from terminal.
5. [LATER] Developer modifies code and runs `azd deploy`
**a. Terminal returns same information to help with next steps.**

**Bold** is the scope of this issue.

## 3. Information to emit

- P0: `Remote MCP server endpoint - https://{function_app_name}.azurewebsites.net/mcp`
- P0: `How do I add my MCP function app as a tool to a Foundry agent? aka.ms/functions-mcp-next-steps`
- _I'm open on the wording_

> [!NOTE]
> Long-term, we should still be emitting the `remote mcp server endpoint`. However, the recommended doc will no longer be necessary once we can automate adding tools to agent.s

## 4. Technical requirements

1. P0: Identify that the function app is a MCP server
2. P0: Construct the endpoint
3. P1: Provide tailored auth recommendations

### 4.1 Identify that the function app is a MCP server

#### 4.1.1. Approach 1 - Interrrogate the function app

Make two api calls since we support two ways of building MCP servers:

- `GET /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{app_name}/functions?api-version=2022-03-01`
- Parse entries for `content.value` for `"properties.config.bindings.type": "mcpToolTrigger"`
- `GET https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{app_name}/hostruntime/admin/vfs//host.json?relativePath=1&api-version=2022-03-01`
- Parse response for `"configurationProfile": "mcp-custom-handler"`

#### 4.1.2 Approach 2 - Infer MCP app from `azure.yaml`

Potentially, we could standardize a way to define a MCP function app. Maybe something like:

```yaml
name: python-mcp-sdk-functions-azd
metadata:
template: python-mcp-sdk-functions-azd@1.0.0
services:
mcp:
project: .
language: python
host: function
```

So, MCP Function app == (`services` is `mcp` AND `host` is `function`)

#### 4.1.3. Approach 3 - Rely on hardcoded outputs

In `main.bicep` we could ensure we output the right endpoint path since the author of the template would know what technology the MCP server is built with.
- `output SERVICE_MCP_ENDPOINT string = '${mcp.outputs.SERVICE_MCP_DEFAULT_HOSTNAME}/mcp'` or
- `output SERVICE_MCP_ENDPOINT string = '${mcp.outputs.SERVICE_MCP_DEFAULT_HOSTNAME}/runtime/webhooks/mcp'`

### 4.2. Construct the endpoint

There are two technologies to build MCP Function apps, each has its own endpoint path:
- **MCP Extension**: `{function_app_default_hostname}/runtime/webhooks/mcp`
- **Self-hosted MCP**: `{function_app_default_hostname}/mcp`

An example of the **MCP Extension** is `https://my-mcp-app.azurewebsites.net/runtime/webhooks/mcp`

### 4.3. Provide tailored auth recommendations

> Out of scope for now, but including for creativity's sake

Theoretically, we could also define somewhere in `/infra` what auth type the function app is using. That way, `azd` can output what `az cli` command to run to fetch that information for the developer - or even ask permission to run it.

Not in scope because if we link to docs, the developer can figure it out themselves.

cc. @rajeshkamal5050

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.