Support for creating self-hosted MCP servers#4789
Conversation
MicroFish91
left a comment
There was a problem hiding this comment.
Mostly nits and questions, LGTM
| "description": "%azureFunctions.allowProgrammingModelSelection%", | ||
| "default": false | ||
| }, | ||
| "azureFunctions.showBallerinaProjectCreation": { |
There was a problem hiding this comment.
Were the ballerina changes intentional?
There was a problem hiding this comment.
Yeah, if you look at this issue: #4749, Lily asked that I remove Ballerina from the project runtimes.
But I didn't have the heart to completely rip out Ballerina since it was a significant open-source contribution. I hid it behind a VS Code setting that users can enable if they need it.
But I did remove the tests for Ballerina since we don't officially support it anymore.
| return !context.functionTemplate && context['buildTool'] !== JavaBuildTool.maven; | ||
| return !context.functionTemplate && | ||
| context['buildTool'] !== JavaBuildTool.maven && | ||
| context.language !== ProjectLanguage.SelfHostedMCPServer; |
There was a problem hiding this comment.
It feels too generous to call an MCP server a project language instead of maybe a project type, although I see the project flow becomes difficult if you don't do it this way (also could introduce a lot of tangential changes).
I still think it could be worth leaving an issue or todo for us to revisit this though, when we have more time to consider all the implications of lumping these together.
There was a problem hiding this comment.
Unfortunately, and I can explain this more tomorrow offline, self-hosted MCP servers are completely handled differently by the runtime. I think the biggest callout is that underneath the hood, the runtime is actually a "custom handler" type which is used to run any server process that you want.
You typically wouldn't want a self-hosted MCP project to be included with a normal functions runtime.
| export class MCPDownloadSnippetsExecuteStep extends AzureWizardExecuteStepWithActivityOutput<MCPProjectWizardContext> { | ||
| stepName: string = 'MCPDownloadSampleCodeExecuteStep'; | ||
| protected getTreeItemLabel(context: MCPProjectWizardContext): string { | ||
| return localize('downloadSampleCode', 'Downloading {0} sample server code', nonNullProp(context, 'serverLanguage')); |
There was a problem hiding this comment.
Nit: Present case for tree item labels
There was a problem hiding this comment.
Will put up a different PR since changing it here will have a bunch of annoying cascading effects.
Use this repository to follow along: https://github.com/Azure-Samples/mcp-sdk-functions-hosting-node
The idea of the MCP in Functions is pretty convoluted, but I'll try my best to explain it here concisely and then explain the changes in this pull request.
All other PRs build off of this one. Don't mind the build errors, I didn't import changes I made in a file because those were more deploy related. When all 3 PRs (#4789, #4790. #4791) are merged, everything should be fine.
There are two ways to have MCP tools in Azure Functions:
Like how it sounds, self-hosted MCP servers are function apps that behave like a remote MCP server. In order to configure the host runtime, there a few things that you have to set in the host.json, but there's a shortcut-- set the
configurationProfileto equal-mcp-custom-handler. The host will see that and set all the defaults required to run the server.Whenever we create the project, we set the workspace setting to indicate that this is a
SelfHostedMcpServer. That comes into play in the deploy scenario.You also need to have a feature flag enabled,
EnableMcpCustomHandlerPreview. This flag is not required for MCP extension function apps.Don't mind the
mcpGetHostKey. That is for the deployment piece, but it was defined in the package.json so I just left it in.