Skip to content

Commit 29e22d8

Browse files
committed
support export filter
1 parent cd9ed64 commit 29e22d8

File tree

4 files changed

+31
-12
lines changed

4 files changed

+31
-12
lines changed

docs/tools/functions_as_tools.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,27 +71,32 @@ If these custom options are not provided, the MCP tool name might default to a d
7171

7272
Beyond customizing individual tool properties at the function deployment level, you can also configure the overall behavior of the "Functions as Tools" feature on the StreamNative MCP Server side using the following environment variables. These variables are typically set when starting the MCP server.
7373

74-
* `PULSAR_FUNCTIONS_POLL_INTERVAL`
74+
* `FUNCTIONS_AS_TOOLS_POLL_INTERVAL`
7575
* **Description**: Controls how frequently the MCP Server polls the Pulsar cluster to discover or update available Pulsar Functions. Setting a lower value means functions are discovered faster, but it may increase the load on the Pulsar cluster.
7676
* **Unit**: Seconds
7777
* **Default**: Defaults to the value specified in `pftools.DefaultManagerOptions()`. Refer to the `pkg/pftools` package for the precise default (e.g., if the internal default is 60 seconds, it will be `60`).
78-
* `PULSAR_FUNCTIONS_TIMEOUT`
78+
* `FUNCTIONS_AS_TOOLS_TIMEOUT`
7979
* **Description**: Sets the default timeout for invoking a Pulsar Function as an MCP tool. If a function execution exceeds this duration, the call will be considered timed out.
8080
* **Unit**: Seconds
8181
* **Default**: Defaults to the value specified in `pftools.DefaultManagerOptions()` (e.g., if the internal default is 30 seconds, it will be `30`).
82-
* `PULSAR_FUNCTIONS_FAILURE_THRESHOLD`
83-
* **Description**: Defines the number of consecutive failures for a specific Pulsar Function tool before it is temporarily moved to a "circuit breaker open" state. In this state, further calls to this specific function tool will be immediately rejected without attempting to execute the function, until the `PULSAR_FUNCTIONS_RESET_TIMEOUT` is reached.
82+
* `FUNCTIONS_AS_TOOLS_FAILURE_THRESHOLD`
83+
* **Description**: Defines the number of consecutive failures for a specific Pulsar Function tool before it is temporarily moved to a "circuit breaker open" state. In this state, further calls to this specific function tool will be immediately rejected without attempting to execute the function, until the `FUNCTIONS_AS_TOOLS_RESET_TIMEOUT` is reached.
8484
* **Unit**: Integer (number of failures)
8585
* **Default**: Defaults to the value specified in `pftools.DefaultManagerOptions()` (e.g., if the internal default is 5, it will be `5`).
86-
* `PULSAR_FUNCTIONS_RESET_TIMEOUT`
86+
* `FUNCTIONS_AS_TOOLS_RESET_TIMEOUT`
8787
* **Description**: Specifies the duration for which a Pulsar Function tool remains in the "circuit breaker open" state (due to exceeding the failure threshold) before the MCP server attempts to reset the circuit and allow calls again.
8888
* **Unit**: Seconds
8989
* **Default**: Defaults to the value specified in `pftools.DefaultManagerOptions()` (e.g., if the internal default is 60 seconds, it will be `60`).
90-
* `PULSAR_FUNCTIONS_TENANT_NAMESPACES`
90+
* `FUNCTIONS_AS_TOOLS_TENANT_NAMESPACES`
9191
* **Description**: A comma-separated list of Pulsar `tenant/namespace` strings that the MCP Server should scan for Pulsar Functions. This allows you to restrict function discovery to specific namespaces. If not set, the server might attempt to discover functions from all namespaces it has access to, as permitted by its Pulsar client configuration.
9292
* **Format**: `tenant1/namespace1,tenant2/namespace2`
9393
* **Example**: `public/default,my-tenant/app-functions`
9494
* **Default**: Empty (meaning discover from all accessible namespaces (only on StreamNative Cloud)).
95+
* `FUNCTIONS_AS_TOOLS_STRICT_EXPORT`
96+
* **Description**: Only export functions with `MCP_TOOL_NAME` and `MCP_TOOL_DESCRIPTION` defined.
97+
* **Format**: `true` or `false`
98+
* **Example**: `false`
99+
* **Default**: `true`
95100

96101
## Considerations and Limitations
97102

pkg/mcp/pulsar_functions_as_tools.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,39 +61,44 @@ func PulsarFunctionManagedMcpTools(s *server.MCPServer, readOnly bool, features
6161

6262
options := pftools.DefaultManagerOptions()
6363

64-
if pollIntervalStr := os.Getenv("PULSAR_FUNCTIONS_POLL_INTERVAL"); pollIntervalStr != "" {
64+
if pollIntervalStr := os.Getenv("FUNCTIONS_AS_TOOLS_POLL_INTERVAL"); pollIntervalStr != "" {
6565
if seconds, err := strconv.Atoi(pollIntervalStr); err == nil && seconds > 0 {
6666
options.PollInterval = time.Duration(seconds) * time.Second
6767
log.Printf("Setting Pulsar Functions poll interval to %v", options.PollInterval)
6868
}
6969
}
7070

71-
if timeoutStr := os.Getenv("PULSAR_FUNCTIONS_TIMEOUT"); timeoutStr != "" {
71+
if timeoutStr := os.Getenv("FUNCTIONS_AS_TOOLS_TIMEOUT"); timeoutStr != "" {
7272
if seconds, err := strconv.Atoi(timeoutStr); err == nil && seconds > 0 {
7373
options.DefaultTimeout = time.Duration(seconds) * time.Second
7474
log.Printf("Setting Pulsar Functions default timeout to %v", options.DefaultTimeout)
7575
}
7676
}
7777

78-
if failureThresholdStr := os.Getenv("PULSAR_FUNCTIONS_FAILURE_THRESHOLD"); failureThresholdStr != "" {
78+
if failureThresholdStr := os.Getenv("FUNCTIONS_AS_TOOLS_FAILURE_THRESHOLD"); failureThresholdStr != "" {
7979
if threshold, err := strconv.Atoi(failureThresholdStr); err == nil && threshold > 0 {
8080
options.FailureThreshold = threshold
8181
log.Printf("Setting Pulsar Functions failure threshold to %d", options.FailureThreshold)
8282
}
8383
}
8484

85-
if resetTimeoutStr := os.Getenv("PULSAR_FUNCTIONS_RESET_TIMEOUT"); resetTimeoutStr != "" {
85+
if resetTimeoutStr := os.Getenv("FUNCTIONS_AS_TOOLS_RESET_TIMEOUT"); resetTimeoutStr != "" {
8686
if seconds, err := strconv.Atoi(resetTimeoutStr); err == nil && seconds > 0 {
8787
options.ResetTimeout = time.Duration(seconds) * time.Second
8888
log.Printf("Setting Pulsar Functions reset timeout to %v", options.ResetTimeout)
8989
}
9090
}
9191

92-
if tenantNamespacesStr := os.Getenv("PULSAR_FUNCTIONS_TENANT_NAMESPACES"); tenantNamespacesStr != "" {
92+
if tenantNamespacesStr := os.Getenv("FUNCTIONS_AS_TOOLS_TENANT_NAMESPACES"); tenantNamespacesStr != "" {
9393
options.TenantNamespaces = strings.Split(tenantNamespacesStr, ",")
9494
log.Printf("Setting Pulsar Functions tenant namespaces to %v", options.TenantNamespaces)
9595
}
9696

97+
if strictExportStr := os.Getenv("FUNCTIONS_AS_TOOLS_STRICT_EXPORT"); strictExportStr != "" {
98+
options.StrictExport = strictExportStr == "true"
99+
log.Printf("Setting Pulsar Functions strict export to %v", options.StrictExport)
100+
}
101+
97102
manager, err := pftools.NewPulsarFunctionManager(s, readOnly, options)
98103
if err != nil {
99104
log.Printf("Failed to create Pulsar Function manager: %v", err)
@@ -102,7 +107,7 @@ func PulsarFunctionManagedMcpTools(s *server.MCPServer, readOnly bool, features
102107

103108
manager.Start()
104109

105-
managerID := "pulsar_functions_manager_" + strconv.FormatInt(time.Now().UnixNano(), 10)
110+
managerID := "FUNCTIONS_AS_TOOLS_manager_" + strconv.FormatInt(time.Now().UnixNano(), 10)
106111
functionManagersLock.Lock()
107112
functionManagers[managerID] = manager
108113
functionManagersLock.Unlock()

pkg/pftools/manager.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ func NewPulsarFunctionManager(mcpServer *server.MCPServer, readOnly bool, option
8282
defaultTimeout: options.DefaultTimeout,
8383
circuitBreakers: make(map[string]*CircuitBreaker),
8484
tenantNamespaces: options.TenantNamespaces,
85+
strictExport: options.StrictExport,
8586
}
8687

8788
return manager, nil
@@ -230,6 +231,11 @@ func (m *PulsarFunctionManager) getFunctionsList() ([]*utils.FunctionConfig, err
230231
}
231232

232233
for _, fn := range allFunctions {
234+
if m.strictExport &&
235+
!strings.Contains(fn.CustomRuntimeOptions, CustomRuntimeOptionsEnvMcpToolNameKey) &&
236+
!strings.Contains(fn.CustomRuntimeOptions, CustomRuntimeOptionsEnvMcpToolDescriptionKey) {
237+
continue
238+
}
233239
status, err := m.adminClient.Functions().GetFunctionStatus(fn.Tenant, fn.Namespace, fn.Name)
234240
if err != nil {
235241
continue

pkg/pftools/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type PulsarFunctionManager struct {
4444
defaultTimeout time.Duration
4545
circuitBreakers map[string]*CircuitBreaker
4646
tenantNamespaces []string
47+
strictExport bool
4748
}
4849

4950
type FunctionTool struct {
@@ -86,6 +87,7 @@ type ManagerOptions struct {
8687
FailureThreshold int
8788
ResetTimeout time.Duration
8889
TenantNamespaces []string
90+
StrictExport bool
8991
}
9092

9193
func DefaultManagerOptions() *ManagerOptions {
@@ -95,5 +97,6 @@ func DefaultManagerOptions() *ManagerOptions {
9597
FailureThreshold: 5,
9698
ResetTimeout: 60 * time.Second,
9799
TenantNamespaces: []string{},
100+
StrictExport: false,
98101
}
99102
}

0 commit comments

Comments
 (0)