Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions resources/backupTemplates/nodejs-4.x/templates/templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -656,5 +656,47 @@
"enabledInTryMode": true,
"userPrompt": []
}
},
{
"id": "McpResourceTrigger-Javascript-4.x",
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Template id uses McpResourceTrigger-Javascript-4.x (lowercase s) whereas other Node v4 JavaScript templates in this file use the -JavaScript-4.x suffix (e.g., McpToolTrigger-JavaScript-4.x). Since template ids act as stable identifiers across providers/feeds, this inconsistency can lead to mismatches or duplicate templates if another source uses the canonical JavaScript id. Consider renaming the id to McpResourceTrigger-JavaScript-4.x to match the established pattern.

Suggested change
"id": "McpResourceTrigger-Javascript-4.x",
"id": "McpResourceTrigger-JavaScript-4.x",

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the other ids are JavaScript. I think we try to normalize all of the ids so that casing shouldn't matter, but you should still be consistent.

"runtime": "2",
"files": {
"%functionName%.js": "const { app } = require('@azure/functions');\n\n// Handler returns the content for the MCP resource when a client reads it.\nasync function mcpResourceHello(_resourceContext, context) {\n context.log('MCP Resource trigger function processed a request.');\n return 'Hello from MCP Resource!';\n}\n\n// Register a file-style MCP resource clients can discover and read.\napp.mcpResource('mcpFileResource', {\n uri: 'file://mcpFileResource.txt',\n resourceName: 'mcpFileResource',\n description: 'Simple MCP Resource that returns text content.',\n mimeType: 'text/plain',\n handler: mcpResourceHello\n});"
},
"metadata": {
"defaultFunctionName": "mcpResourceTrigger",
"description": "$McpResourceTrigger_description",
"name": "MCP Resource Trigger",
"language": "JavaScript",
"triggerType": "mcpResourceTrigger",
"category": [
"$temp_category_core",
"$temp_category_dataProcessing"
],
"categoryStyle": "other",
"enabledInTryMode": false,
"userPrompt": []
}
},
{
"id": "McpResourceTrigger-TypeScript-4.x",
"runtime": "2",
"files": {
"%functionName%.ts": "import { app, InvocationContext } from \"@azure/functions\";\n\n// Handler returns the content for the MCP resource when a client reads it.\nexport async function mcpResourceHello(_resourceContext: unknown, context: InvocationContext): Promise<string> {\n context.log('MCP Resource trigger function processed a request.');\n return 'Hello from MCP Resource!';\n}\n\n// Register a file-style MCP resource clients can discover and read.\napp.mcpResource('mcpFileResource', {\n uri: 'file://mcpFileResource.txt',\n resourceName: 'mcpFileResource',\n description: 'Simple MCP Resource that returns text content.',\n mimeType: 'text/plain',\n handler: mcpResourceHello\n});"
},
"metadata": {
"defaultFunctionName": "mcpResourceTrigger",
"description": "$McpResourceTrigger_description",
"name": "MCP Resource Trigger",
"language": "TypeScript",
"triggerType": "mcpResourceTrigger",
"category": [
"$temp_category_core",
"$temp_category_dataProcessing"
],
"categoryStyle": "other",
"enabledInTryMode": false,
"userPrompt": []
}
}
]
10 changes: 5 additions & 5 deletions src/funcConfig/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ export class ParsedFunctionJson {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public constructor(data: any) {

if (typeof data === 'object' && data !== null && (data.triggerType !== undefined)) {
this.template = <IFunctionTemplate>data;
this.data = {};
}

else if (typeof data === 'object' && data !== null && (data.bindings === undefined || data.bindings instanceof Array)) {
this.data = <IFunctionJson>data;

} else {
this.data = {};
}
Expand Down Expand Up @@ -85,10 +85,10 @@ export class ParsedFunctionJson {

public get isMcpTrigger(): boolean {
if (this.template?.triggerType) {
return /^mcptooltrigger/i.test(this.template.triggerType) || /^mcptrigger/i.test(this.template.triggerType);
return /^mcptooltrigger/i.test(this.template.triggerType) || /^mcptrigger/i.test(this.template.triggerType) || /^mcpresourcetrigger/i.test(this.template.triggerType);
}
if (this.triggerBinding && this.triggerBinding.type) {
return /^mcptooltrigger/i.test(this.triggerBinding.type) || /^mcptrigger/i.test(this.triggerBinding.type);
return /^mcptooltrigger/i.test(this.triggerBinding.type) || /^mcptrigger/i.test(this.triggerBinding.type) || /^mcpresourcetrigger/i.test(this.triggerBinding.type);
}

return false;
Expand Down
1 change: 1 addition & 0 deletions src/templates/script/getScriptVerifiedTemplateIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function getScriptVerifiedTemplateIds(version: string): (string | RegExp)
'EventGridBlobTrigger',
'SqlTrigger',
'McpToolTrigger',
'McpResourceTrigger',
'MCPTrigger'
]);

Expand Down
5 changes: 3 additions & 2 deletions src/templates/script/parseScriptTemplatesV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ export function parseScriptTemplates(rawTemplates: RawTemplateV2[], rawBindings:
}
const isHttpTrigger = !!templateV2.id?.toLowerCase().includes('httptrigger-');
const isTimerTrigger = !!templateV2.id?.toLowerCase().includes('timertrigger-');
// python and node.js use 2 different IDs for Mcp Triggers... because of course they do
// MCP trigger variants use multiple IDs across templates/providers.
const isMcpTrigger = !!templateV2.id?.toLowerCase().includes('mcptooltrigger') ||
templateV2.id?.toLowerCase().includes('mcptrigger');
templateV2.id?.toLowerCase().includes('mcptrigger') ||
templateV2.id?.toLowerCase().includes('mcpresourcetrigger');

templates.push(Object.assign(templateV2, {
wizards: parsedJobs,
Expand Down
4 changes: 2 additions & 2 deletions test/templateCount.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ function addSuite(source: TemplateSource | undefined): void {
suite(`Template Count - ${source === undefined ? 'defaultOnExtensionActivation' : source}`, () => {
const cases: TestCase[] = [
{ language: ProjectLanguage.JavaScript, version: FuncVersion.v1, expectedCount: 8 },
{ language: ProjectLanguage.JavaScript, version: FuncVersion.v4, expectedCount: 18 },
{ language: ProjectLanguage.JavaScript, version: FuncVersion.v4, expectedCount: 18, backupExpectedCount: 19 },
{ language: ProjectLanguage.CSharp, version: FuncVersion.v1, expectedCount: 12 },
{ language: ProjectLanguage.CSharp, version: FuncVersion.v4, expectedCount: 15, projectTemplateKey: 'net6.0' },
{ language: ProjectLanguage.CSharp, version: FuncVersion.v4, expectedCount: 14, backupExpectedCount: 13, projectTemplateKey: 'net6.0-isolated' },
{ language: ProjectLanguage.CSharp, version: FuncVersion.v4, expectedCount: 14, backupExpectedCount: 13, projectTemplateKey: 'net7.0-isolated' },
{ language: ProjectLanguage.CSharp, version: FuncVersion.v4, expectedCount: 14, backupExpectedCount: 13, projectTemplateKey: 'net8.0-isolated' },
{ language: ProjectLanguage.Python, version: FuncVersion.v4, expectedCount: 15 },
{ language: ProjectLanguage.TypeScript, version: FuncVersion.v4, expectedCount: 18 },
{ language: ProjectLanguage.TypeScript, version: FuncVersion.v4, expectedCount: 18, backupExpectedCount: 19 },
{ language: ProjectLanguage.PowerShell, version: FuncVersion.v4, expectedCount: 16 },
{ language: ProjectLanguage.Ballerina, version: FuncVersion.v4, expectedCount: 5 }
];
Expand Down
Loading