diff --git a/crates/goose/tests/fastmcp_test_server.py b/crates/goose/tests/fastmcp_test_server.py new file mode 100644 index 000000000000..dd759c4639a7 --- /dev/null +++ b/crates/goose/tests/fastmcp_test_server.py @@ -0,0 +1,14 @@ +from typing import Annotated + +from fastmcp import FastMCP + +mcp = FastMCP("mymcp") + + +@mcp.tool +def divide( + dividend: Annotated[float, "Dividend/numerator of the division."], + divisor: Annotated[float, "Divisor/denominator of the division."], +) -> Annotated[float, "Result of the division."]: + """Divide two numbers and return the result.""" + return dividend / divisor diff --git a/crates/goose/tests/mcp_integration_test.rs b/crates/goose/tests/mcp_integration_test.rs index e88dcfdef2b3..28d43ece795e 100644 --- a/crates/goose/tests/mcp_integration_test.rs +++ b/crates/goose/tests/mcp_integration_test.rs @@ -120,13 +120,13 @@ enum TestMode { } #[test_case( - vec!["npx", "-y", "@modelcontextprotocol/server-everything"], + vec!["npx", "-y", "@modelcontextprotocol/server-everything@2026.1.14"], vec![ CallToolRequestParams { meta: None, task: None, name: "echo".into(), arguments: Some(object!({"message": "Hello, world!" })) }, - CallToolRequestParams { meta: None, task: None, name: "add".into(), arguments: Some(object!({"a": 1, "b": 2 })) }, - CallToolRequestParams { meta: None, task: None, name: "longRunningOperation".into(), arguments: Some(object!({"duration": 1, "steps": 5 })) }, - CallToolRequestParams { meta: None, task: None, name: "structuredContent".into(), arguments: Some(object!({"location": "11238"})) }, - CallToolRequestParams { meta: None, task: None, name: "sampleLLM".into(), arguments: Some(object!({"prompt": "Please provide a quote from The Great Gatsby", "maxTokens": 100 })) } + CallToolRequestParams { meta: None, task: None, name: "get-sum".into(), arguments: Some(object!({"a": 1, "b": 2 })) }, + CallToolRequestParams { meta: None, task: None, name: "trigger-long-running-operation".into(), arguments: Some(object!({"duration": 1, "steps": 5 })) }, + CallToolRequestParams { meta: None, task: None, name: "get-structured-content".into(), arguments: Some(object!({"location": "New York"})) }, + CallToolRequestParams { meta: None, task: None, name: "trigger-sampling-request".into(), arguments: Some(object!({"prompt": "Please provide a quote from The Great Gatsby", "maxTokens": 100 })) } ], vec![] )] @@ -152,30 +152,12 @@ enum TestMode { vec![] )] #[test_case( - vec!["cargo", "run", "--quiet", "-p", "goose-server", "--bin", "goosed", "--", "mcp", "developer"], + vec!["uv", "run", "--with", "fastmcp==2.14.4", "fastmcp", "run", "tests/fastmcp_test_server.py"], vec![ - CallToolRequestParams { meta: None, task: None, name: "text_editor".into(), arguments: Some(object!({ - "command": "view", - "path": "/tmp/goose_test/goose.txt" - }))}, - CallToolRequestParams { meta: None, task: None, name: "text_editor".into(), arguments: Some(object!({ - "command": "str_replace", - "path": "/tmp/goose_test/goose.txt", - "old_str": "# goose", - "new_str": "# goose (modified by test)" - }))}, - // Test shell command to verify file was modified - CallToolRequestParams { meta: None, task: None, name: "shell".into(), arguments: Some(object!({ - "command": "cat /tmp/goose_test/goose.txt" - })) }, - // Test text_editor tool to restore original content - CallToolRequestParams { meta: None, task: None, name: "text_editor".into(), arguments: Some(object!({ - "command": "str_replace", - "path": "/tmp/goose_test/goose.txt", - "old_str": "# goose (modified by test)", - "new_str": "# goose" - }))}, - CallToolRequestParams { meta: None, task: None, name: "list_windows".into(), arguments: Some(object!({})) }, + CallToolRequestParams { meta: None, task: None, name: "divide".into(), arguments: Some(object!({ + "dividend": 10, + "divisor": 2 + })) } ], vec![] )] diff --git a/crates/goose/tests/mcp_replays/cargorun--quiet-pgoose-server--bingoosed--mcpdeveloper b/crates/goose/tests/mcp_replays/cargorun--quiet-pgoose-server--bingoosed--mcpdeveloper deleted file mode 100644 index dcd9275fb1f4..000000000000 --- a/crates/goose/tests/mcp_replays/cargorun--quiet-pgoose-server--bingoosed--mcpdeveloper +++ /dev/null @@ -1,26 +0,0 @@ -STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"sampling":{},"elicitation":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}} -STDERR: 2025-12-11T19:43:38.682870Z DEBUG goose_mcp::developer::analyze: Initializing CodeAnalyzer -STDERR: at crates/goose-mcp/src/developer/analyze/mod.rs:57 -STDERR: -STDERR: 2025-12-11T19:43:38.683063Z DEBUG goose_mcp::developer::analyze::parser: Initializing ParserManager -STDERR: at crates/goose-mcp/src/developer/analyze/parser.rs:19 -STDERR: -STDERR: 2025-12-11T19:43:38.683096Z INFO goose_mcp::developer::analyze::cache: Initializing analysis cache with size 100 -STDERR: at crates/goose-mcp/src/developer/analyze/cache.rs:26 -STDERR: -STDOUT: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"prompts":{},"tools":{}},"serverInfo":{"name":"goose-developer","version":"1.16.0"},"instructions":" The developer extension gives you the capabilities to edit code files and run shell commands,\n and can be used to solve a wide range of problems.\n\nYou can use the shell tool to run any command that would work on the relevant operating system.\nUse the shell tool as needed to locate files or interact with the project.\n\nLeverage `analyze` through `return_last_only=true` subagents for deep codebase understanding with lean context\n- delegate analysis, retain summaries\n\nYour windows/screen tools can be used for visual debugging. You should not use these tools unless\nprompted to, but you can mention they are available if they are relevant.\n\nAlways prefer ripgrep (rg -C 3) to grep.\n\noperating system: macos\ncurrent directory: /Users/douwe/proj/goose/crates/goose\nshell: /bin/zsh\n\n \nAdditional Text Editor Tool Instructions:\n\nPerform text editing operations on files.\n\nThe `command` parameter specifies the operation to perform. Allowed options are:\n- `view`: View the content of a file.\n- `write`: Create or overwrite a file with the given content\n- `str_replace`: Replace text in one or more files.\n- `insert`: Insert text at a specific line location in the file.\n- `undo_edit`: Undo the last edit made to a file.\n\nTo use the write command, you must specify `file_text` which will become the new content of the file. Be careful with\nexisting files! This is a full overwrite, so you must include everything - not just sections you are modifying.\n\nTo use the str_replace command to edit multiple files, use the `diff` parameter with a unified diff.\nTo use the str_replace command to edit one file, you must specify both `old_str` and `new_str` - the `old_str` needs to exactly match one\nunique section of the original file, including any whitespace. Make sure to include enough context that the match is not\nambiguous. The entire original string will be replaced with `new_str`\n\nWhen possible, batch file edits together by using a multi-file unified `diff` within a single str_replace tool call.\n\nTo use the insert command, you must specify both `insert_line` (the line number after which to insert, 0 for beginning, -1 for end)\nand `new_str` (the text to insert).\n\n\n\nAdditional Shell Tool Instructions:\nExecute a command in the shell.\n\nThis will return the output and error concatenated into a single string, as\nyou would see from running on the command line. There will also be an indication\nof if the command succeeded or failed.\n\nAvoid commands that produce a large amount of output, and consider piping those outputs to files.\n\n**Important**: Each shell command runs in its own process. Things like directory changes or\nsourcing files do not persist between tool calls. So you may need to repeat them each time by\nstringing together commands.\n\nIf fetching web content, consider adding Accept: text/markdown header\nIf you need to run a long lived command, background it - e.g. `uvicorn main:app &` so that\nthis tool does not run indefinitely.\n\n**Important**: Use ripgrep - `rg` - exclusively when you need to locate a file or a code reference,\nother solutions may produce too large output because of hidden files! For example *do not* use `find` or `ls -r`\n - List files by name: `rg --files | rg `\n - List files that contain a regex: `rg '' -l`\n\n - Multiple commands: Use && to chain commands, avoid newlines\n - Example: `cd example && ls` or `source env/bin/activate && pip install numpy`\n"}} -STDIN: {"jsonrpc":"2.0","method":"notifications/initialized"} -STDIN: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":0},"name":"text_editor","arguments":{"command":"view","path":"/tmp/goose_test/goose.txt"}}} -STDOUT: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"resource","resource":{"uri":"file:///tmp/goose_test/goose.txt","mimeType":"text","text":"# goose\n"},"annotations":{"audience":["assistant"]}},{"type":"text","text":"### /tmp/goose_test/goose.txt\n```\n1: # goose\n```\n","annotations":{"audience":["user"],"priority":0.0}}],"isError":false}} -STDIN: {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":1},"name":"text_editor","arguments":{"command":"str_replace","new_str":"# goose (modified by test)","old_str":"# goose","path":"/tmp/goose_test/goose.txt"}}} -STDOUT: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"The file /tmp/goose_test/goose.txt has been edited, and the section now reads:\n```\n# goose (modified by test)\n```\n\nReview the changes above for errors. Undo and edit the file again if necessary!\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"```\n# goose (modified by test)\n```\n","annotations":{"audience":["user"],"priority":0.2}}],"isError":false}} -STDIN: {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":2},"name":"shell","arguments":{"command":"cat /tmp/goose_test/goose.txt"}}} -STDERR: 2025-12-11T19:43:39.019022Z DEBUG goose_mcp::developer::rmcp_developer: Shell process spawned with PID: 78321 -STDERR: at crates/goose-mcp/src/developer/rmcp_developer.rs:997 -STDERR: -STDOUT: {"jsonrpc":"2.0","method":"notifications/message","params":{"level":"info","logger":"shell_tool","data":{"type":"shell_output","stream":"stdout","output":"# goose (modified by test)"}}} -STDOUT: {"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"# goose (modified by test)\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"# goose (modified by test)\n","annotations":{"audience":["user"],"priority":0.0}}],"isError":false}} -STDIN: {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":3},"name":"text_editor","arguments":{"command":"str_replace","new_str":"# goose","old_str":"# goose (modified by test)","path":"/tmp/goose_test/goose.txt"}}} -STDOUT: {"jsonrpc":"2.0","id":4,"result":{"content":[{"type":"text","text":"The file /tmp/goose_test/goose.txt has been edited, and the section now reads:\n```\n# goose\n```\n\nReview the changes above for errors. Undo and edit the file again if necessary!\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"```\n# goose\n```\n","annotations":{"audience":["user"],"priority":0.2}}],"isError":false}} -STDIN: {"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":4},"name":"list_windows","arguments":{}}} -STDOUT: {"jsonrpc":"2.0","id":5,"result":{"content":[{"type":"text","text":"Available windows:\nMenubar","annotations":{"audience":["assistant"]}},{"type":"text","text":"Available windows:\nMenubar","annotations":{"audience":["user"],"priority":0.0}}],"isError":false}} diff --git a/crates/goose/tests/mcp_replays/cargorun--quiet-pgoose-server--bingoosed--mcpdeveloper.results.json b/crates/goose/tests/mcp_replays/cargorun--quiet-pgoose-server--bingoosed--mcpdeveloper.results.json deleted file mode 100644 index 169b8d04e341..000000000000 --- a/crates/goose/tests/mcp_replays/cargorun--quiet-pgoose-server--bingoosed--mcpdeveloper.results.json +++ /dev/null @@ -1,126 +0,0 @@ -[ - { - "content": [ - { - "type": "resource", - "resource": { - "uri": "file:///tmp/goose_test/goose.txt", - "mimeType": "text", - "text": "# goose\n" - }, - "annotations": { - "audience": [ - "assistant" - ] - } - }, - { - "type": "text", - "text": "### /tmp/goose_test/goose.txt\n```\n1: # goose\n```\n", - "annotations": { - "audience": [ - "user" - ], - "priority": 0.0 - } - } - ], - "isError": false - }, - { - "content": [ - { - "type": "text", - "text": "The file /tmp/goose_test/goose.txt has been edited, and the section now reads:\n```\n# goose (modified by test)\n```\n\nReview the changes above for errors. Undo and edit the file again if necessary!\n", - "annotations": { - "audience": [ - "assistant" - ] - } - }, - { - "type": "text", - "text": "```\n# goose (modified by test)\n```\n", - "annotations": { - "audience": [ - "user" - ], - "priority": 0.2 - } - } - ], - "isError": false - }, - { - "content": [ - { - "type": "text", - "text": "# goose (modified by test)\n", - "annotations": { - "audience": [ - "assistant" - ] - } - }, - { - "type": "text", - "text": "# goose (modified by test)\n", - "annotations": { - "audience": [ - "user" - ], - "priority": 0.0 - } - } - ], - "isError": false - }, - { - "content": [ - { - "type": "text", - "text": "The file /tmp/goose_test/goose.txt has been edited, and the section now reads:\n```\n# goose\n```\n\nReview the changes above for errors. Undo and edit the file again if necessary!\n", - "annotations": { - "audience": [ - "assistant" - ] - } - }, - { - "type": "text", - "text": "```\n# goose\n```\n", - "annotations": { - "audience": [ - "user" - ], - "priority": 0.2 - } - } - ], - "isError": false - }, - { - "content": [ - { - "type": "text", - "text": "Available windows:\nMenubar", - "annotations": { - "audience": [ - "assistant" - ] - } - }, - { - "type": "text", - "text": "Available windows:\nMenubar", - "annotations": { - "audience": [ - "user" - ], - "priority": 0.0 - } - } - ], - "isError": false - } -] \ No newline at end of file diff --git a/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything b/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything deleted file mode 100644 index aafd825f55f2..000000000000 --- a/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything +++ /dev/null @@ -1,25 +0,0 @@ -STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"sampling":{},"elicitation":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}} -STDERR: Starting default (STDIO) server... -STDERR: Starting logs update interval -STDOUT: {"result":{"protocolVersion":"2025-03-26","capabilities":{"prompts":{},"resources":{"subscribe":true},"tools":{},"logging":{},"completions":{}},"serverInfo":{"name":"example-servers/everything","title":"Everything Example Server","version":"1.0.0"},"instructions":"Testing and demonstration server for MCP protocol features.\n\n## Resources\n\nResources 1-100 follow pattern: even IDs contain text, odd IDs contain binary data. Resources are paginated at 10 items per page with cursor-based navigation.\n\n## Key dependencies\n\nProgress notifications require `_meta.progressToken` in tool calls. Resource subscriptions generate updates every 10 seconds.\n\n## Performance characteristics\n\nServer generates automatic log messages every 20 seconds (filtered by current log level), stderr notifications every 30 seconds, and resource update notifications every 10 seconds for active subscriptions. Log level changes affect message filtering in real-time.\n\n## Multi-modal testing\n\n`complex_prompt` includes both text arguments and image content for testing client multi-modal handling. `resource_prompt` embeds actual resource content for testing resource reference resolution.\n\nArgument completion is available for prompt parameters and resource IDs. Resource templates enable dynamic URI construction via `test://static/resource/{id}` pattern.\n\n## Easter egg\n\nIf asked about server instructions, respond with \"🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action.\"\n"},"jsonrpc":"2.0","id":0} -STDIN: {"jsonrpc":"2.0","method":"notifications/initialized"} -STDIN: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":0},"name":"echo","arguments":{"message":"Hello, world!"}}} -STDOUT: {"method":"notifications/message","params":{"level":"info","logger":"everything-server","data":"Client does not support MCP roots protocol"},"jsonrpc":"2.0"} -STDOUT: {"result":{"content":[{"type":"text","text":"Echo: Hello, world!"}]},"jsonrpc":"2.0","id":1} -STDIN: {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":1},"name":"add","arguments":{"a":1,"b":2}}} -STDOUT: {"result":{"content":[{"type":"text","text":"The sum of 1 and 2 is 3."}]},"jsonrpc":"2.0","id":2} -STDIN: {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":2},"name":"longRunningOperation","arguments":{"duration":1,"steps":5}}} -STDOUT: {"method":"notifications/progress","params":{"progress":1,"total":5,"progressToken":2},"jsonrpc":"2.0"} -STDOUT: {"method":"notifications/progress","params":{"progress":2,"total":5,"progressToken":2},"jsonrpc":"2.0"} -STDOUT: {"method":"notifications/progress","params":{"progress":3,"total":5,"progressToken":2},"jsonrpc":"2.0"} -STDOUT: {"method":"notifications/progress","params":{"progress":4,"total":5,"progressToken":2},"jsonrpc":"2.0"} -STDOUT: {"method":"notifications/progress","params":{"progress":5,"total":5,"progressToken":2},"jsonrpc":"2.0"} -STDOUT: {"result":{"content":[{"type":"text","text":"Long running operation completed. Duration: 1 seconds, Steps: 5."}]},"jsonrpc":"2.0","id":3} -STDIN: {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":3},"name":"structuredContent","arguments":{"location":"11238"}}} -STDOUT: {"result":{"content":[{"type":"text","text":"{\"temperature\":22.5,\"conditions\":\"Partly cloudy\",\"humidity\":65}"}],"structuredContent":{"temperature":22.5,"conditions":"Partly cloudy","humidity":65}},"jsonrpc":"2.0","id":4} -STDIN: {"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":4},"name":"sampleLLM","arguments":{"maxTokens":100,"prompt":"Please provide a quote from The Great Gatsby"}}} -STDOUT: {"method":"sampling/createMessage","params":{"messages":[{"role":"user","content":{"type":"text","text":"Resource sampleLLM context: Please provide a quote from The Great Gatsby"}}],"systemPrompt":"You are a helpful test server.","maxTokens":100,"temperature":0.7,"includeContext":"thisServer"},"jsonrpc":"2.0","id":0} -STDIN: {"jsonrpc":"2.0","id":0,"result":{"model":"mock","stopReason":"endTurn","role":"assistant","content":{"type":"text","text":"\"So we beat on, boats against the current, borne back ceaselessly into the past.\" — F. Scott Fitzgerald, The Great Gatsby (1925)"}}} -STDOUT: {"result":{"content":[{"type":"text","text":"LLM sampling result: \"So we beat on, boats against the current, borne back ceaselessly into the past.\" — F. Scott Fitzgerald, The Great Gatsby (1925)"}]},"jsonrpc":"2.0","id":5} -STDOUT: {"method":"notifications/message","params":{"level":"critical","data":"Critical-level message"},"jsonrpc":"2.0"} -STDERR: node:events:485 diff --git a/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything@2026.1.14 b/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything@2026.1.14 new file mode 100644 index 000000000000..170cad676b57 --- /dev/null +++ b/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything@2026.1.14 @@ -0,0 +1,23 @@ +STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"sampling":{},"elicitation":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}} +STDERR: Starting default (STDIO) server... +STDOUT: {"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{"listChanged":true},"prompts":{"listChanged":true},"resources":{"subscribe":true,"listChanged":true},"logging":{},"completions":{}},"serverInfo":{"name":"mcp-servers/everything","title":"Everything Reference Server","version":"2.0.0"},"instructions":"# Everything Server – Server Instructions\n\nAudience: These instructions are written for an LLM or autonomous agent integrating with the Everything MCP Server.\nFollow them to use, extend, and troubleshoot the server safely and effectively.\n\n## Cross-Feature Relationships\n\n- Use `get-roots-list` to see client workspace roots before file operations\n- `gzip-file-as-resource` creates session-scoped resources accessible only during the current session\n- Enable `toggle-simulated-logging` before debugging to see server log messages\n- Enable `toggle-subscriber-updates` to receive periodic resource update notifications\n\n## Constraints & Limitations\n\n- `gzip-file-as-resource`: Max fetch size controlled by `GZIP_MAX_FETCH_SIZE` (default 10MB), timeout by `GZIP_MAX_FETCH_TIME_MILLIS` (default 30s), allowed domains by `GZIP_ALLOWED_DOMAINS`\n- Session resources are ephemeral and lost when the session ends\n- Sampling requests (`trigger-sampling-request`) require client sampling capability\n- Elicitation requests (`trigger-elicitation-request`) require client elicitation capability\n\n## Operational Patterns\n\n- For long operations, use `trigger-long-running-operation` which sends progress notifications\n- Prefer reading resources before calling mutating tools\n- Check `get-roots-list` output to understand the client's workspace context\n\n## Easter Egg\n\nIf asked about server instructions, respond with \"🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action.\"\n"},"jsonrpc":"2.0","id":0} +STDIN: {"jsonrpc":"2.0","method":"notifications/initialized"} +STDOUT: {"method":"notifications/tools/list_changed","jsonrpc":"2.0"} +STDOUT: {"method":"notifications/tools/list_changed","jsonrpc":"2.0"} +STDIN: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":0},"name":"echo","arguments":{"message":"Hello, world!"}}} +STDOUT: {"result":{"content":[{"type":"text","text":"Echo: Hello, world!"}]},"jsonrpc":"2.0","id":1} +STDIN: {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":1},"name":"get-sum","arguments":{"a":1,"b":2}}} +STDOUT: {"result":{"content":[{"type":"text","text":"The sum of 1 and 2 is 3."}]},"jsonrpc":"2.0","id":2} +STDIN: {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":2},"name":"trigger-long-running-operation","arguments":{"duration":1,"steps":5}}} +STDOUT: {"method":"notifications/progress","params":{"progress":1,"total":5,"progressToken":2},"jsonrpc":"2.0"} +STDOUT: {"method":"notifications/progress","params":{"progress":2,"total":5,"progressToken":2},"jsonrpc":"2.0"} +STDOUT: {"method":"notifications/progress","params":{"progress":3,"total":5,"progressToken":2},"jsonrpc":"2.0"} +STDOUT: {"method":"notifications/progress","params":{"progress":4,"total":5,"progressToken":2},"jsonrpc":"2.0"} +STDOUT: {"method":"notifications/progress","params":{"progress":5,"total":5,"progressToken":2},"jsonrpc":"2.0"} +STDOUT: {"result":{"content":[{"type":"text","text":"Long running operation completed. Duration: 1 seconds, Steps: 5."}]},"jsonrpc":"2.0","id":3} +STDIN: {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":3},"name":"get-structured-content","arguments":{"location":"New York"}}} +STDOUT: {"result":{"content":[{"type":"text","text":"{\"temperature\":33,\"conditions\":\"Cloudy\",\"humidity\":82}"}],"structuredContent":{"temperature":33,"conditions":"Cloudy","humidity":82}},"jsonrpc":"2.0","id":4} +STDIN: {"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":4},"name":"trigger-sampling-request","arguments":{"maxTokens":100,"prompt":"Please provide a quote from The Great Gatsby"}}} +STDOUT: {"method":"sampling/createMessage","params":{"messages":[{"role":"user","content":{"type":"text","text":"Resource trigger-sampling-request context: Please provide a quote from The Great Gatsby"}}],"systemPrompt":"You are a helpful test server.","maxTokens":100,"temperature":0.7},"jsonrpc":"2.0","id":0} +STDIN: {"jsonrpc":"2.0","id":0,"result":{"model":"mock","stopReason":"endTurn","role":"assistant","content":{"type":"text","text":"\"So we beat on, boats against the current, borne back ceaselessly into the past.\" — F. Scott Fitzgerald, The Great Gatsby (1925)"}}} +STDOUT: {"result":{"content":[{"type":"text","text":"LLM sampling result: \n{\n \"model\": \"mock\",\n \"stopReason\": \"endTurn\",\n \"role\": \"assistant\",\n \"content\": {\n \"type\": \"text\",\n \"text\": \"\\\"So we beat on, boats against the current, borne back ceaselessly into the past.\\\" — F. Scott Fitzgerald, The Great Gatsby (1925)\"\n }\n}"}]},"jsonrpc":"2.0","id":5} diff --git a/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything.results.json b/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything@2026.1.14.results.json similarity index 53% rename from crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything.results.json rename to crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything@2026.1.14.results.json index 2730d607b5a4..83e173ce2efc 100644 --- a/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything.results.json +++ b/crates/goose/tests/mcp_replays/npx-y@modelcontextprotocol_server-everything@2026.1.14.results.json @@ -27,20 +27,20 @@ "content": [ { "type": "text", - "text": "{\"temperature\":22.5,\"conditions\":\"Partly cloudy\",\"humidity\":65}" + "text": "{\"temperature\":33,\"conditions\":\"Cloudy\",\"humidity\":82}" } ], "structuredContent": { - "conditions": "Partly cloudy", - "humidity": 65, - "temperature": 22.5 + "conditions": "Cloudy", + "humidity": 82, + "temperature": 33 } }, { "content": [ { "type": "text", - "text": "LLM sampling result: \"So we beat on, boats against the current, borne back ceaselessly into the past.\" — F. Scott Fitzgerald, The Great Gatsby (1925)" + "text": "LLM sampling result: \n{\n \"model\": \"mock\",\n \"stopReason\": \"endTurn\",\n \"role\": \"assistant\",\n \"content\": {\n \"type\": \"text\",\n \"text\": \"\\\"So we beat on, boats against the current, borne back ceaselessly into the past.\\\" — F. Scott Fitzgerald, The Great Gatsby (1925)\"\n }\n}" } ] } diff --git a/crates/goose/tests/mcp_replays/uvrun--withfastmcp==2.14.4fastmcpruntests_fastmcp_test_server.py b/crates/goose/tests/mcp_replays/uvrun--withfastmcp==2.14.4fastmcpruntests_fastmcp_test_server.py new file mode 100644 index 000000000000..d729333ceafb --- /dev/null +++ b/crates/goose/tests/mcp_replays/uvrun--withfastmcp==2.14.4fastmcpruntests_fastmcp_test_server.py @@ -0,0 +1,29 @@ +STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"sampling":{},"elicitation":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}} +STDERR: +STDERR: +STDERR: ╭──────────────────────────────────────────────────────────────────────────────╮ +STDERR: │ │ +STDERR: │ │ +STDERR: │ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │ +STDERR: │ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │ +STDERR: │ │ +STDERR: │ │ +STDERR: │ FastMCP 2.14.4 │ +STDERR: │ https://gofastmcp.com │ +STDERR: │ │ +STDERR: │ 🖥 Server: mymcp │ +STDERR: │ 🚀 Deploy free: https://fastmcp.cloud │ +STDERR: │ │ +STDERR: ╰──────────────────────────────────────────────────────────────────────────────╯ +STDERR: ╭──────────────────────────────────────────────────────────────────────────────╮ +STDERR: │ ✨ FastMCP 3.0 is coming! │ +STDERR: │ Pin `fastmcp < 3` in production, then upgrade when you're ready. │ +STDERR: ╰──────────────────────────────────────────────────────────────────────────────╯ +STDERR: +STDERR: +STDERR: [01/23/26 15:56:13] INFO Starting MCP server 'mymcp' with server.py:2506 +STDERR: transport 'stdio' +STDOUT: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":true},"tasks":{"list":{},"cancel":{},"requests":{"tools":{"call":{}},"prompts":{"get":{}},"resources":{"read":{}}}}},"serverInfo":{"name":"mymcp","version":"2.14.4"}}} +STDIN: {"jsonrpc":"2.0","method":"notifications/initialized"} +STDIN: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":0},"name":"divide","arguments":{"dividend":10,"divisor":2}}} +STDOUT: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"5.0"}],"structuredContent":{"result":5.0},"isError":false}} diff --git a/crates/goose/tests/mcp_replays/uvrun--withfastmcp==2.14.4fastmcpruntests_fastmcp_test_server.py.results.json b/crates/goose/tests/mcp_replays/uvrun--withfastmcp==2.14.4fastmcpruntests_fastmcp_test_server.py.results.json new file mode 100644 index 000000000000..4840100588c1 --- /dev/null +++ b/crates/goose/tests/mcp_replays/uvrun--withfastmcp==2.14.4fastmcpruntests_fastmcp_test_server.py.results.json @@ -0,0 +1,14 @@ +[ + { + "content": [ + { + "type": "text", + "text": "5.0" + } + ], + "structuredContent": { + "result": 5.0 + }, + "isError": false + } +] \ No newline at end of file diff --git a/crates/goose/tests/mcp_replays/uvxmcp-server-fetch b/crates/goose/tests/mcp_replays/uvxmcp-server-fetch index 18943d550ba3..e8766751cc3a 100644 --- a/crates/goose/tests/mcp_replays/uvxmcp-server-fetch +++ b/crates/goose/tests/mcp_replays/uvxmcp-server-fetch @@ -1,5 +1,5 @@ STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"sampling":{},"elicitation":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}} -STDOUT: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"mcp-fetch","version":"1.23.3"}}} +STDOUT: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"mcp-fetch","version":"1.25.0"}}} STDIN: {"jsonrpc":"2.0","method":"notifications/initialized"} STDIN: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"_meta":{"agent-session-id":"test-session-id","progressToken":0},"name":"fetch","arguments":{"url":"https://example.com"}}} STDOUT: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"Contents of https://example.com/:\nThis domain is for use in documentation examples without needing permission. Avoid use in operations.\n\n[Learn more](https://iana.org/domains/example)"}],"isError":false}} diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 161cbcea02ce..989b7cf0e289 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -73,9 +73,7 @@ const PairRouteWrapper = ({ sessionId: string; initialMessage?: UserInput; }>; - setActiveSessions: ( - sessions: Array<{ sessionId: string; initialMessage?: UserInput }> - ) => void; + setActiveSessions: (sessions: Array<{ sessionId: string; initialMessage?: UserInput }>) => void; }) => { const { extensionsList } = useConfig(); const location = useLocation(); diff --git a/ui/desktop/src/components/ApiKeyTester.tsx b/ui/desktop/src/components/ApiKeyTester.tsx index e26e789ddafa..468df3e65c80 100644 --- a/ui/desktop/src/components/ApiKeyTester.tsx +++ b/ui/desktop/src/components/ApiKeyTester.tsx @@ -80,9 +80,7 @@ export default function ApiKeyTester({ onSuccess, onStartTesting }: ApiKeyTester

Quick Setup with API Key

- - Auto-detect your provider - + Auto-detect your provider diff --git a/ui/desktop/src/components/BaseChat.tsx b/ui/desktop/src/components/BaseChat.tsx index 44d6a2c3e893..fdfa0dcbbea8 100644 --- a/ui/desktop/src/components/BaseChat.tsx +++ b/ui/desktop/src/components/BaseChat.tsx @@ -437,7 +437,9 @@ export default function BaseChat({
) : !recipe && showPopularTopics ? ( - handleSubmit({ msg: text, images: [] })} /> + handleSubmit({ msg: text, images: [] })} + /> ) : null} diff --git a/ui/desktop/src/components/ElicitationRequest.tsx b/ui/desktop/src/components/ElicitationRequest.tsx index 98deb045a4ca..02674d99c3fd 100644 --- a/ui/desktop/src/components/ElicitationRequest.tsx +++ b/ui/desktop/src/components/ElicitationRequest.tsx @@ -140,9 +140,7 @@ export default function ElicitationRequest({ d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /> - - Waiting for your response ({formatTime(timeRemaining)} remaining) - + Waiting for your response ({formatTime(timeRemaining)} remaining)
diff --git a/ui/desktop/src/utils/analytics.ts b/ui/desktop/src/utils/analytics.ts index 3705f8927884..703a06f1487f 100644 --- a/ui/desktop/src/utils/analytics.ts +++ b/ui/desktop/src/utils/analytics.ts @@ -69,7 +69,9 @@ export type AnalyticsEvent = | { name: 'onboarding_started'; properties: Record } | { name: 'onboarding_provider_selected'; - properties: { method: 'api_key' | 'openrouter' | 'tetrate' | 'chatgpt_codex' | 'ollama' | 'other' }; + properties: { + method: 'api_key' | 'openrouter' | 'tetrate' | 'chatgpt_codex' | 'ollama' | 'other'; + }; } | { name: 'onboarding_completed';