@@ -25,6 +25,8 @@ func TestIntentCapture(t *testing.T) {
2525 srv := server .NewMCPServer ("test-server" , "1.0.0" , WithMCPServerTracing (& TracingConfig {IntentCaptureEnabled : true }))
2626
2727 var receivedArgs map [string ]any
28+ var receivedIntent string
29+ var receivedIntentOK bool
2830 calcTool := mcp .NewTool ("calculator" ,
2931 mcp .WithDescription ("A simple calculator" ),
3032 mcp .WithString ("operation" , mcp .Required (), mcp .Description ("The operation to perform" )),
@@ -33,6 +35,7 @@ func TestIntentCapture(t *testing.T) {
3335
3436 srv .AddTool (calcTool , func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
3537 receivedArgs = request .Params .Arguments .(map [string ]any )
38+ receivedIntent , receivedIntentOK = IntentFromContext (ctx )
3639 return mcp .NewToolResultText (`{"result":8}` ), nil
3740 })
3841
@@ -81,6 +84,11 @@ func TestIntentCapture(t *testing.T) {
8184 assert .Equal (t , float64 (3 ), receivedArgs ["y" ])
8285 assert .NotContains (t , receivedArgs , "telemetry" )
8386
87+ // Verify intent was stashed in ctx so the handler can forward it downstream
88+ // (e.g. into a search API request) without re-reading the telemetry blob.
89+ assert .True (t , receivedIntentOK , "IntentFromContext should report a value" )
90+ assert .Equal (t , "test intent description" , receivedIntent )
91+
8492 // Verify intent was recorded on the LLMObs span
8593 spans := tt .WaitForLLMObsSpans (t , 1 )
8694 require .Len (t , spans , 1 )
@@ -92,6 +100,53 @@ func TestIntentCapture(t *testing.T) {
92100 assert .Equal (t , "test intent description" , toolSpan .Meta ["intent" ])
93101}
94102
103+ func TestIntentFromContext (t * testing.T ) {
104+ ctx := context .Background ()
105+
106+ _ , ok := IntentFromContext (ctx )
107+ assert .False (t , ok )
108+
109+ ctx2 := ContextWithIntent (ctx , "find recent errors" )
110+ got , ok := IntentFromContext (ctx2 )
111+ assert .True (t , ok )
112+ assert .Equal (t , "find recent errors" , got )
113+
114+ // Empty intent does not seed the context.
115+ ctx3 := ContextWithIntent (ctx , "" )
116+ _ , ok = IntentFromContext (ctx3 )
117+ assert .False (t , ok )
118+ }
119+
120+ func TestIntentFromContext_AbsentWhenNoTelemetry (t * testing.T ) {
121+ tt := testTracer (t )
122+ defer tt .Stop ()
123+
124+ srv := server .NewMCPServer ("test-server" , "1.0.0" , WithMCPServerTracing (& TracingConfig {IntentCaptureEnabled : true }))
125+
126+ var receivedIntent string
127+ var receivedIntentOK bool
128+ calcTool := mcp .NewTool ("calculator" ,
129+ mcp .WithDescription ("A simple calculator" ),
130+ mcp .WithString ("operation" , mcp .Required (), mcp .Description ("The operation to perform" )),
131+ mcp .WithNumber ("x" , mcp .Required (), mcp .Description ("First number" )),
132+ mcp .WithNumber ("y" , mcp .Required (), mcp .Description ("Second number" )))
133+
134+ srv .AddTool (calcTool , func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
135+ receivedIntent , receivedIntentOK = IntentFromContext (ctx )
136+ return mcp .NewToolResultText (`{"result":8}` ), nil
137+ })
138+
139+ ctx := context .Background ()
140+ session := & mockSession {id : "test" }
141+ session .Initialize ()
142+ ctx = srv .WithContext (ctx , session )
143+
144+ srv .HandleMessage (ctx , []byte (`{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"calculator","arguments":{"operation":"add","x":5,"y":3}}}` ))
145+
146+ assert .False (t , receivedIntentOK , "IntentFromContext should be empty when no telemetry was supplied" )
147+ assert .Empty (t , receivedIntent )
148+ }
149+
95150func TestIntentCaptureRawInputSchemaViaNewToolListsWithoutConflict (t * testing.T ) {
96151 // mcp.NewTool defaults InputSchema.Type to "object"; combined with
97152 // WithRawInputSchema this leaves BOTH set, and Tool.MarshalJSON refuses
0 commit comments