77using ModelContextProtocol;
88using ModelContextProtocol . Client ;
99using OpenAI . Chat ;
10+ using System . Text . Json ;
1011
1112string mcpCommand = Environment . GetEnvironmentVariable ( "MCP_SERVER_COMMAND" ) ! ; // path to a stdio mcp server
1213string key = Environment . GetEnvironmentVariable ( "OPENAI_API_KEY" ) ! ;
2324
2425// get avaliable tools and add them to completion options
2526ChatCompletionOptions options = new ( ) ;
26- await foreach ( McpClientTool chatTool in mcpClient . EnumerateToolsAsync ( ) )
27+ await foreach ( McpClientTool tool in mcpClient . EnumerateToolsAsync ( ) )
2728{
28- options . Tools . Add ( chatTool . AsOpenAIChatTool ( ) ) ;
29+ options . Tools . Add ( ChatTool . CreateFunctionTool ( tool . Name , tool . Description , BinaryData . FromString ( tool . JsonSchema . GetRawText ( ) ) ) ) ;
2930}
3031
3132// conversation thread
4041switch ( chatCompletion . FinishReason )
4142{
4243 case ChatFinishReason . ToolCalls :
43- foreach ( var call in chatCompletion . ToolCalls )
44+ foreach ( var call in chatCompletion . ToolCalls )
4445 {
4546 var mcpArguments = call . FunctionArguments . ToObjectFromJson < Dictionary < string , object > > ( ) ;
4647 Console . WriteLine ( "Tool call detected, calling MCP server..." ) ;
47- ModelContextProtocol . Protocol . CallToolResult result = await mcpClient . CallToolAsync ( call . FunctionName , mcpArguments ! ) ;
48- Console . WriteLine ( $ "tool call result { result . Content [ 0 ] } ") ;
49- ChatMessage message = call . ToMessage ( result . Content . ToAIContents ( ) ) ;
50- conversation . Add ( message ) ;
51- }
48+ var result = await mcpClient . CallToolAsync ( call . FunctionName , mcpArguments ! ) ;
49+ Console . WriteLine ( $ "Tool call result { result . Content [ 0 ] } ") ;
50+ conversation . Add ( ChatMessage . CreateToolMessage ( call . Id , JsonSerializer . Serialize ( result ) ) ) ;
51+ }
5252 goto start ;
5353 case ChatFinishReason . Stop :
5454 Console . WriteLine ( chatCompletion . Content [ 0 ] . Text ) ;
5555 break ;
5656 default :
5757 throw new NotImplementedException ( ) ;
58- }
59-
60- #region TEMPORARY
61- // this is temporary. all these APIs will endup being in one of the packages used here.
62- public static class TemporaryExtensions
63- {
64- // this needs to be in the adapter package
65- public static ChatMessage ToMessage ( this ChatToolCall openaiCall , IEnumerable < Microsoft . Extensions . AI . AIContent > contents )
66- {
67- List < ChatMessageContentPart > parts = new ( ) ;
68- foreach ( Microsoft . Extensions . AI . AIContent content in contents )
69- {
70- string serialized = System . Text . Json . JsonSerializer . Serialize ( content . RawRepresentation ) ;
71- using System . Text . Json . JsonDocument json = System . Text . Json . JsonDocument . Parse ( serialized ) ;
72- System . Text . Json . JsonElement text = json . RootElement . GetProperty ( "text" ) ;
73- string textValue = text . GetString ( ) ?? string . Empty ;
74- parts . Add ( ChatMessageContentPart . CreateTextPart ( textValue ) ) ;
75- }
76- ToolChatMessage message = ChatMessage . CreateToolMessage ( openaiCall . Id , parts ) ;
77- return message ;
78- }
79-
80- // this is in the adapter package
81- public static ChatTool AsOpenAIChatTool ( this Microsoft . Extensions . AI . AIFunction mcpTool )
82- {
83- return ChatTool . CreateFunctionTool (
84- mcpTool . Name ,
85- mcpTool . Description ,
86- BinaryData . FromString ( mcpTool . JsonSchema . GetRawText ( ) ) ) ;
87- }
88- }
89- #endregion
58+ }
0 commit comments