-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
[BUG] Workflows exposed as MCP tools receive empty RuntimeContext, preventing access to authentication
Description
When workflows are exposed via MCPServer, they always receive an empty RuntimeContext
regardless of the authentication context available at execution time. This prevents workflows from accessing authentication information passed through options.extra
.
Steps to Reproduce
- Create a workflow that requires authentication:
const myWorkflow = createWorkflow({
id: 'my-workflow',
description: 'A workflow that needs auth',
steps: [],
inputSchema: z.object({ data: z.string() }),
outputSchema: z.object({ result: z.string() })
})
.then(createStep({
id: 'auth-step',
execute: async ({ inputData, runtimeContext }) => {
// This will always be undefined when called via MCP
const authToken = runtimeContext.get('authToken');
if (!authToken) {
throw new Error('Authentication required');
}
// ... do work
}
}))
.commit();
- Expose it via MCPServer:
const server = new MCPServer({
name: 'My Server',
workflows: {
myWorkflow
}
});
- Set up authentication middleware:
// Middleware that sets req.auth
app.use((req, res, next) => {
req.auth = { authToken: 'token123' };
next();
});
- Call the workflow tool via MCP - it will fail with "Authentication required"
Expected Behavior
The workflow should receive the authentication context from options.extra.authInfo
or through the runtimeContext
parameter, similar to how regular tools work.
Actual Behavior
The workflow always receives an empty RuntimeContext()
because:
convertWorkflowsToTools
creates a new empty RuntimeContext at tool creation time:
// In packages/mcp/src/server/server.ts
const options = {
runtimeContext: new RuntimeContext(), // Always empty!
// ...
};
const coreTool = makeCoreTool(workflowToolDefinition, options);
CoreToolBuilder.createExecute
uses the creation-time RuntimeContext, not the execution-time context:
// The runtimeContext used is from options (creation time),
// not from execOptions (execution time)
runtimeContext: options.runtimeContext ?? new RuntimeContext()
Root Cause Analysis
The issue occurs because:
makeCoreTool
is called with a static emptyRuntimeContext
during workflow-to-tool conversion- The execution-time
options.extra
(which contains authInfo) is never used to populate the runtimeContext - Unlike regular tools which can access
options.extra
directly, workflow steps only receiveruntimeContext
Proposed Solutions
The following approaches could fix this issue:
Option 1: Pass execution-time context (Recommended)
Modify CoreToolBuilder.createExecute
to check for runtime context in execOptions:
runtimeContext: execOptions.runtimeContext ?? options.runtimeContext ?? new RuntimeContext()
This maintains backward compatibility while allowing runtime context injection.
Option 2: Populate RuntimeContext from options.extra
Before calling the workflow, populate the RuntimeContext from options.extra.authInfo
:
if (options.extra?.authInfo) {
Object.entries(options.extra.authInfo).forEach(([key, value]) => {
runtimeContext.set(key, value);
});
}
This approach automatically maps auth info to the runtime context.
Option 3: Pass options.extra to workflow steps
Allow workflow steps to access options.extra
directly, similar to regular tools.
This would require more significant API changes but provides maximum flexibility.
Impact
- Workflows that need authentication cannot be used via MCP
- This limits the usefulness of exposing workflows through MCP servers
- Workaround requires using individual tools instead of workflows
Environment
- @mastra/core: 0.16.0
- @mastra/mcp: 0.12.0
- Node.js: 20.x
- TypeScript: 5.x
Related Code References
packages/mcp/src/server/server.ts
-convertWorkflowsToTools
methodpackages/core/src/tool/builder.ts
-CoreToolBuilder.createExecute
method
Workaround
Currently, the only workaround is to not expose workflows via MCP and use individual tools instead, or ensure workflows only use tools internally (which get their own auth context) rather than accessing runtimeContext directly in steps.
Additional Context
This issue was discovered when trying to expose workflows that require authentication through an MCP server. Regular tools work fine because they can access options.extra.requestInfo.headers
or options.extra.authInfo
, but workflows don't have access to these.
The same issue likely affects agents converted to tools via convertAgentsToTools
, which also creates an empty RuntimeContext.