Skip to content
Closed
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
8 changes: 6 additions & 2 deletions packages/agents-core/src/tracing/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@ export async function getOrCreateTrace<T>(

/**
* This function will set the current span in the execution context.
* If no trace context exists, the operation is skipped.
*
* @param span - The span to set as the current span.
*/
export function setCurrentSpan(span: Span<any>) {
const context = getContextAsyncLocalStorage().getStore();
if (!context) {
throw new Error('No existing trace found');
// No trace context exists, skip setting the span
return;
}

if (context.span) {
Expand Down Expand Up @@ -173,13 +175,15 @@ export function cloneCurrentContext(context: ContextState) {

/**
* This function will run the given function with a new span context.
* If no trace context exists, the function will be executed directly without tracing.
*
* @param fn - The function to run with the new span context.
*/
export function withNewSpanContext<T>(fn: () => Promise<T>) {
const currentContext = getContextAsyncLocalStorage().getStore();
if (!currentContext) {
throw new Error('No existing trace found');
// No trace context exists, run the function directly without tracing
return fn();
}

const copyOfContext = cloneCurrentContext(currentContext);
Expand Down
108 changes: 108 additions & 0 deletions packages/agents-core/test/mcpNoTraceContext.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { describe, test, expect } from 'vitest';
import { Agent } from '../src/agent';
import { RunContext } from '../src/runContext';
import type { MCPServer } from '../src/mcp';

describe('MCP Tools without Trace Context', () => {
test('should fetch MCP tools without requiring a trace context', async () => {
// Create a mock MCP server
const mockMcpServer: MCPServer = {
name: 'test-mcp-server',
cacheToolsList: false,
async connect() {
return;
},
async close() {
return;
},
async listTools() {
return [
{
name: 'test_tool',
description: 'A test tool',
inputSchema: {
type: 'object' as const,
properties: {
input: { type: 'string' },
},
required: [],
additionalProperties: false,
},
},
];
},
async callTool() {
return [{ type: 'text', text: 'test result' }];
},
async invalidateToolsCache() {
return;
},
};

// Create an agent with MCP server (no trace context)
const agent = new Agent({
name: 'test-agent',
instructions: 'Test agent',
mcpServers: [mockMcpServer],
});

// Create a run context without a trace
const context = new RunContext({});

// This should not throw "No existing trace found" error
const mcpTools = await agent.getMcpTools(context);

expect(mcpTools).toBeDefined();
expect(mcpTools.length).toBe(1);
expect(mcpTools[0].name).toBe('test_tool');
});

test('should get all tools including MCP tools without trace context', async () => {
const mockMcpServer: MCPServer = {
name: 'test-mcp-server',
cacheToolsList: false,
async connect() {
return;
},
async close() {
return;
},
async listTools() {
return [
{
name: 'mcp_tool',
description: 'An MCP tool',
inputSchema: {
type: 'object' as const,
properties: {},
required: [],
additionalProperties: false,
},
},
];
},
async callTool() {
return [{ type: 'text', text: 'result' }];
},
async invalidateToolsCache() {
return;
},
};

const agent = new Agent({
name: 'test-agent',
instructions: 'Test agent',
mcpServers: [mockMcpServer],
tools: [],
});

const context = new RunContext({});

// This should work without throwing an error
const allTools = await agent.getAllTools(context);

expect(allTools).toBeDefined();
expect(allTools.length).toBe(1);
expect(allTools[0].name).toBe('mcp_tool');
});
});