Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azure/functions",
"version": "4.11.2",
"version": "4.12.0",
"description": "Microsoft Azure Functions NodeJS Framework",
"keywords": [
"azure",
Expand Down
12 changes: 12 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HttpHandler,
HttpMethod,
HttpMethodFunctionOptions,
McpResourceFunctionOptions,
McpToolFunctionOptions,
MySqlFunctionOptions,
ServiceBusQueueFunctionOptions,
Expand Down Expand Up @@ -157,6 +158,17 @@ export function mcpTool(name: string, options: McpToolFunctionOptions): void {
generic(name, convertToGenericOptions(options, trigger.mcpTool));
}

/**
* Registers an MCP Resource function in your app.
* This function is triggered when an MCP client reads the resource and allows you to define the resource content.
*
* @param name - The name of the function. This must be unique within your app and is primarily used for tracking purposes.
* @param options - Configuration options for the MCP Resource function, including the handler and trigger-specific settings.
*/
export function mcpResource(name: string, options: McpResourceFunctionOptions): void {
generic(name, convertToGenericOptions(options, trigger.mcpResource));
}

export function generic(name: string, options: GenericFunctionOptions): void {
if (!hasSetModel) {
setProgrammingModel();
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

export const version = '4.11.2';
export const version = '4.12.0';

export const returnBindingKey = '$return';
60 changes: 60 additions & 0 deletions src/converters/toMcpResourceTriggerOptionsToRpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

import { McpResourceTriggerOptions } from '../../types';

/**
* Validates and returns an McpResourceTriggerOptions object.
*
* @param options - The input options to validate.
* @returns The validated McpResourceTriggerOptions object.
* @throws Error if required properties are missing or invalid.
*/
export function convertToMcpResourceTriggerOptionsToRpc(options: McpResourceTriggerOptions): McpResourceTriggerOptions {
// Validate required properties
if (!options.uri || typeof options.uri !== 'string' || options.uri.trim() === '') {
throw new Error('MCP Resource trigger requires a valid "uri" property.');
}

if (!options.resourceName || typeof options.resourceName !== 'string' || options.resourceName.trim() === '') {
throw new Error('MCP Resource trigger requires a valid "resourceName" property.');
}

// Build the result object with required properties
const result: McpResourceTriggerOptions = {
uri: options.uri,
resourceName: options.resourceName,
};

// Add optional properties if they are defined
if (options.title !== undefined) {
result.title = options.title;
}

if (options.description !== undefined) {
result.description = options.description;
}

if (options.mimeType !== undefined) {
result.mimeType = options.mimeType;
}

if (options.size !== undefined) {
if (typeof options.size !== 'number' || options.size < 0) {
throw new Error('MCP Resource trigger "size" must be a non-negative number.');
}
result.size = options.size;
}

if (options.metadata !== undefined && typeof options.metadata === 'string' && options.metadata.trim() !== '') {
// Validate that metadata is a valid JSON string
try {
JSON.parse(options.metadata);
} catch (e) {
throw new Error('MCP Resource trigger "metadata" must be a valid JSON string.');
}
result.metadata = options.metadata;
}

return result;
}
18 changes: 17 additions & 1 deletion src/converters/toMcpToolTriggerOptionsToRpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,26 @@ import { normalizeToolProperties } from '../utils/toolProperties';
export function converToMcpToolTriggerOptionsToRpc(
mcpToolTriggerOptions: McpToolTriggerOptions
): McpToolTriggerOptionsToRpc {
// Base object for the return value
// Validate metadata if provided - skip empty/whitespace strings
let validatedMetadata: string | undefined;
if (
mcpToolTriggerOptions.metadata !== undefined &&
typeof mcpToolTriggerOptions.metadata === 'string' &&
mcpToolTriggerOptions.metadata.trim() !== ''
) {
try {
JSON.parse(mcpToolTriggerOptions.metadata);
validatedMetadata = mcpToolTriggerOptions.metadata;
} catch (e) {
throw new Error('MCP Tool trigger "metadata" must be a valid JSON string.');
}
}

// Base object for the return value - metadata is independent of toolProperties
const baseResult = {
toolName: mcpToolTriggerOptions.toolName,
description: mcpToolTriggerOptions.description,
...(validatedMetadata !== undefined && { metadata: validatedMetadata }),
};

// Try to normalize tool properties first (handles both array and fluent formats)
Expand Down
18 changes: 18 additions & 0 deletions src/trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
GenericTriggerOptions,
HttpTrigger,
HttpTriggerOptions,
McpResourceTrigger,
McpResourceTriggerOptions,
McpToolTrigger,
McpToolTriggerOptions,
MySqlTrigger,
Expand All @@ -34,6 +36,7 @@ import {
WebPubSubTriggerOptions,
} from '@azure/functions';
import { addBindingName } from './addBindingName';
import { convertToMcpResourceTriggerOptionsToRpc } from './converters/toMcpResourceTriggerOptionsToRpc';
import { converToMcpToolTriggerOptionsToRpc } from './converters/toMcpToolTriggerOptionsToRpc';

export function http(options: HttpTriggerOptions): HttpTrigger {
Expand Down Expand Up @@ -143,6 +146,21 @@ export function mcpTool(options: McpToolTriggerOptions): McpToolTrigger {
});
}

/**
* Creates an MCP Resource trigger configuration.
* This function is used to define an MCP Resource trigger for an Azure Function.
* MCP Resources are read-only data sources that can be accessed by MCP clients.
*
* @param options - The configuration options for the MCP Resource trigger, including resource-specific metadata.
* @returns An MCP Resource trigger object with the specified configuration.
*/
export function mcpResource(options: McpResourceTriggerOptions): McpResourceTrigger {
return addTriggerBindingName({
...convertToMcpResourceTriggerOptionsToRpc(options),
type: 'mcpResourceTrigger',
});
}

export function generic(options: GenericTriggerOptions): FunctionTrigger {
return addTriggerBindingName(options);
}
Expand Down
Loading
Loading