goose icon indicating copy to clipboard operation
goose copied to clipboard

Goose session invalid after tool call interruption

Open wendytang opened this issue 9 months ago • 10 comments

Describe the bug When users interrupt goose mid tool-call, the session is no longer valid

Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: {"external_model_provider":"amazon-bedrock","external_model_error":{"message":"messages.2: Did not find 1 tool_result block(s) at the beginning of this message. Messages following tool_use blocks must begin with a matching number of tool_result blocks."}}.

Please retry if you think this is a transient or recoverable error.

To Reproduce Steps to reproduce the behavior:

  1. Open up goose app
  2. Ask goose to do something which calls a tool
  3. Interrupt goose
  4. Ask the question again

Expected behavior Goose should be able to handle interruptions and continue

Screenshots

Image

Please provide following information:

  • OS & Arch: Mac M1 Max
  • Interface: UI
  • Version: latest
  • Extensions enabled: None
  • Provider & Model: Claude-sonnet-3.5

Additional I believe the same issue arises in the CLI.

wendytang avatar Mar 11 '25 20:03 wendytang

Is this on the canary? We were tracking something similar in https://github.com/block/goose/issues/1541 and a PR https://github.com/block/goose/pull/1557.

I was only able to replicate it in the UI though and all my attempts in CLI didn't replicate it, if you're seeing it in the CLI can you paste the exact sequence you were using?

kalvinnchau avatar Mar 11 '25 23:03 kalvinnchau

@kalvinnchau I have an example of seeing this in the CLI in #1600

trobrock avatar Mar 12 '25 11:03 trobrock

#1651

wendytang avatar Mar 13 '25 00:03 wendytang

1.0.14 continues to have this issue.

CyphrRiot avatar Mar 14 '25 18:03 CyphrRiot

@HunterR0se can you provide more information please What tool call did you interrupt, was it a long tool call or a chain of calls, and can you provide your session file to aid in debugging?

kalvinnchau avatar Mar 14 '25 19:03 kalvinnchau

@kalvinnchau

I've just installed Goose and encountered a similar issue on my first attempt using the CLI on Linux. Seems to be a rate limiting issue, although not throwing a 429 (which I'm seeing when using a gemini model).

System information

  • OS & Arch: Ubuntu 22.04.5 LTS (Jammy Jellyfish)
  • Interface: CLI
  • Version: 1.0.14
  • Extensions enabled: computercontroller, developer, github, memory
  • Provider & Model: Anthropic / claude-3-5-sonnet-latest (I have a gut feeling i originally set the model to claude-3.7-sonnet, but it's changed?)

Error encountered

When attempting to create a GitHub branch, update a README, and open a PR, I received a similar error. The session becomes unusable after this and subsequent commands result in the same error throwing. New sessions also throw the same error after one prompt.

Error: Request failed: Request failed with status: 400 Bad Request. Message: messages.5: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01BfF7yoP8tv5AM4W4qdVygC. Each `tool_use` block must have a corresponding `tool_result` block in the next message.

Session history

See below.. Looks like it starts during the sequence of GitHub API calls.

Seems like it's just hitting the Anthropic limits.. I suspect the issue is just related to token limits being reached during the chain of thought (?).

Hard to tell as i've only just gotten start using goose and unsure what a response would typically look like here, but i imagine the agent is beginning to churn tokens trying to resolve the 422, then the token limit (50 requests per minute, 40,000 input tokens per minute) is reached?

Execution failed: RPC error: code=-32603, message=Validation Error: Validation Failed
Details: {"message":"Validation Failed","errors":[{"resource":"PullRequest","field":"base","code":"invalid"}],"documentation_url":"https://docs.github.com/rest/pulls/pulls#create-a-pull-request","status":"422"}

Hard to tell from my claude dashboard as i tried a few prompts afterward to debug... But it looks like my token usage was somewhere between 30-50k+ tokens for that original prompt. Can take a look into the token usage further if you need.

Looking into OpenRouter and self hosting tonight to work around..

Full session log

Click to expand session log file
[
    {
        "working_dir": "/home/user",
        "description": "GitHub Branch Repository Issues",
        "message_count": 6,
        "total_tokens": 12172
    },
    {
        "role": "user",
        "created": 1742265425,
        "content": [
            {
                "type": "text",
                "text": "create a new branch called hello-world in my tibia-oce/server repository. Update the README.md file to say \"this was written by goose\" and commit it. Open a pull request with your changes."
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265434,
        "content": [
            {
                "type": "text",
                "text": "I'll help you create a branch, update the README, and open a pull request. Let's break this down into steps:\n\n1. First, let's create the new branch called \"hello-world\":"
            },
            {
                "type": "toolRequest",
                "id": "toolu_01C8ku4wfvFVZcv2WZ1STeKG",
                "toolCall": {
                    "status": "success",
                    "value": {
                        "name": "github__create_branch",
                        "arguments": {
                            "branch": "hello-world",
                            "owner": "tibia-oce",
                            "repo": "server"
                        }
                    }
                }
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265434,
        "content": [
            {
                "type": "toolResponse",
                "id": "toolu_01C8ku4wfvFVZcv2WZ1STeKG",
                "toolResult": {
                    "status": "success",
                    "value": [
                        {
                            "type": "text",
                            "text": "{\n  \"ref\": \"refs/heads/hello-world\",\n  \"node_id\": \"REF_kwDOMn-d17ZyZWZzL2hlYWRzL2hlbGxvLXdvcmxk\",\n  \"url\": \"https://api.github.com/repos/tibia-oce/server/git/refs/heads/hello-world\",\n  \"object\": {\n    \"sha\": \"b27d6bcd3530223f052780c4e59dfbd115072879\",\n    \"type\": \"commit\",\n    \"url\": \"https://api.github.com/repos/tibia-oce/server/git/commits/b27d6bcd3530223f052780c4e59dfbd115072879\"\n  }\n}"
                        }
                    ]
                }
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265440,
        "content": [
            {
                "type": "text",
                "text": "2. Now, let's update the README.md file with the new content:"
            },
            {
                "type": "toolRequest",
                "id": "toolu_01XCF1q95usmBpVawAiUfxiv",
                "toolCall": {
                    "status": "success",
                    "value": {
                        "name": "github__create_or_update_file",
                        "arguments": {
                            "branch": "hello-world",
                            "content": "this was written by goose",
                            "message": "Update README.md with goose message",
                            "owner": "tibia-oce",
                            "path": "README.md",
                            "repo": "server"
                        }
                    }
                }
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265440,
        "content": [
            {
                "type": "toolResponse",
                "id": "toolu_01XCF1q95usmBpVawAiUfxiv",
                "toolResult": {
                    "status": "success",
                    "value": [
                        {
                            "type": "text",
                            "text": "{\n  \"content\": {\n    \"name\": \"README.md\",\n    \"path\": \"README.md\",\n    \"sha\": \"a9ffaecab7293a0344eb6be5f5ab797e6f900ed4\",\n    \"size\": 25,\n    \"url\": \"https://api.github.com/repos/tibia-oce/server/contents/README.md?ref=hello-world\",\n    \"html_url\": \"https://github.com/tibia-oce/server/blob/hello-world/README.md\",\n    \"git_url\": \"https://api.github.com/repos/tibia-oce/server/git/blobs/a9ffaecab7293a0344eb6be5f5ab797e6f900ed4\",\n    \"download_url\": \"https://raw.githubusercontent.com/tibia-oce/server/hello-world/README.md\",\n    \"type\": \"file\",\n    \"_links\": {\n      \"self\": \"https://api.github.com/repos/tibia-oce/server/contents/README.md?ref=hello-world\",\n      \"git\": \"https://api.github.com/repos/tibia-oce/server/git/blobs/a9ffaecab7293a0344eb6be5f5ab797e6f900ed4\",\n      \"html\": \"https://github.com/tibia-oce/server/blob/hello-world/README.md\"\n    }\n  },\n  \"commit\": {\n    \"sha\": \"607a4aca90ecf41ccfee9b98c20f1a263e92a24e\",\n    \"node_id\": \"C_kwDOMn-d19oAKDYwN2E0YWNhOTBlY2Y0MWNjZmVlOWI5OGMyMGYxYTI2M2U5MmEyNGU\",\n    \"url\": \"https://api.github.com/repos/tibia-oce/server/git/commits/607a4aca90ecf41ccfee9b98c20f1a263e92a24e\",\n    \"html_url\": \"https://github.com/tibia-oce/server/commit/607a4aca90ecf41ccfee9b98c20f1a263e92a24e\",\n    \"author\": {\n      \"name\": \"Jordan Hoare\",\n      \"email\": \"[email protected]\",\n      \"date\": \"2025-03-18T02:37:20Z\"\n    },\n    \"committer\": {\n      \"name\": \"Jordan Hoare\",\n      \"email\": \"[email protected]\",\n      \"date\": \"2025-03-18T02:37:20Z\"\n    },\n    \"message\": \"Update README.md with goose message\",\n    \"tree\": {\n      \"sha\": \"3c914b89e37817ac29f3e820443b845355264267\",\n      \"url\": \"https://api.github.com/repos/tibia-oce/server/git/trees/3c914b89e37817ac29f3e820443b845355264267\"\n    },\n    \"parents\": [\n      {\n        \"sha\": \"b27d6bcd3530223f052780c4e59dfbd115072879\",\n        \"url\": \"https://api.github.com/repos/tibia-oce/server/git/commits/b27d6bcd3530223f052780c4e59dfbd115072879\",\n        \"html_url\": \"https://github.com/tibia-oce/server/commit/b27d6bcd3530223f052780c4e59dfbd115072879\"\n      }\n    ]\n  }\n}"
                        }
                    ]
                }
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265445,
        "content": [
            {
                "type": "text",
                "text": "3. Finally, let's create a pull request with these changes:"
            },
            {
                "type": "toolRequest",
                "id": "toolu_01BfF7yoP8tv5AM4W4qdVygC",
                "toolCall": {
                    "status": "success",
                    "value": {
                        "name": "github__create_pull_request",
                        "arguments": {
                            "base": "main",
                            "body": "Added a message to README.md written by Goose.",
                            "head": "hello-world",
                            "owner": "tibia-oce",
                            "repo": "server",
                            "title": "Update README.md"
                        }
                    }
                }
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265445,
        "content": [
            {
                "type": "toolResponse",
                "id": "toolu_01BfF7yoP8tv5AM4W4qdVygC",
                "toolResult": {
                    "status": "error",
                    "error": "Execution failed: RPC error: code=-32603, message=Validation Error: Validation Failed\nDetails: {\"message\":\"Validation Failed\",\"errors\":[{\"resource\":\"PullRequest\",\"field\":\"base\",\"code\":\"invalid\"}],\"documentation_url\":\"https://docs.github.com/rest/pulls/pulls#create-a-pull-request\",\"status\":\"422\"}"
                }
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265445,
        "content": [
            {
                "type": "text",
                "text": "Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages.5: Messages containing `tool_use` blocks must be followed by a user message with `tool_result` blocks.\n\nPlease retry if you think this is a transient or recoverable error."
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265772,
        "content": [
            {
                "type": "text",
                "text": "the last command failed due to this error: Execution failed: RPC error: code=-32603, message=Validation Error: Validation Failed\nDetails: {\"message\":\"Validation Failed\",\"errors\":[{\"resource\":\"PullRequest\",\"field\":\"base\",\"code\":\"invalid\"}],\"documentation_url\":\"https://docs.github.com/rest/pulls/pulls#create-a-pull-request\",\"status\":\"422\"}\n\u25d0  Waddling through workflows...                                                                                                    2025-03-18T02:37:25.744554Z ERROR goose::agents::truncate: Error: Request failed: Request failed with status: 400 Bad Request. Message: messages.5: Messages containing `tool_use` blocks must be followed by a user message with `tool_result` blocks\n    at crates/goose/src/agents/truncate.rs:464\n\nRan into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages.5: Messages containing `tool_use` blocks must be followed by a user message with `tool_result` blocks.\n\nPlease retry if you think this is a transient or recoverable error."
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265774,
        "content": [
            {
                "type": "text",
                "text": "Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages.6: Did not find 1 `tool_result` block(s) at the beginning of this message. Messages following `tool_use` blocks must begin with a matching number of `tool_result` blocks..\n\nPlease retry if you think this is a transient or recoverable error."
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265786,
        "content": [
            {
                "type": "text",
                "text": "clear"
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265789,
        "content": [
            {
                "type": "text",
                "text": "Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages.5: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01BfF7yoP8tv5AM4W4qdVygC. Each `tool_use` block must have a corresponding `tool_result` block in the next message..\n\nPlease retry if you think this is a transient or recoverable error."
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265792,
        "content": [
            {
                "type": "text",
                "text": "hello"
            }
        ]
    },
    {
        "role": "assistant",
        "created": 1742265792,
        "content": [
            {
                "type": "text",
                "text": "Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages.5: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01BfF7yoP8tv5AM4W4qdVygC. Each `tool_use` block must have a corresponding `tool_result` block in the next message..\n\nPlease retry if you think this is a transient or recoverable error."
            }
        ]
    }
]

jordanhoare avatar Mar 18 '25 03:03 jordanhoare

@jordanhoare Thanks for the details and the session file, that definitely looks strange. From your session file the error:

 Message: messages.5: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01BfF7yoP8tv5AM4W4qdVygC.

But we can see the full matching toolRequest (tool_use) and toolResponse (tool_result) with matching ID's.

    {
        "role": "assistant",
        "created": 1742265445,
        "content": [
            {
                "type": "text",
                "text": "3. Finally, let's create a pull request with these changes:"
            },
            {
                "type": "toolRequest",
                "id": "toolu_01BfF7yoP8tv5AM4W4qdVygC",
                "toolCall": {
                    "status": "success",
                    "value": {
                        "name": "github__create_pull_request",
                        "arguments": {
                            "base": "main",
                            "body": "Added a message to README.md written by Goose.",
                            "head": "hello-world",
                            "owner": "tibia-oce",
                            "repo": "server",
                            "title": "Update README.md"
                        }
                    }
                }
            }
        ]
    },
    {
        "role": "user",
        "created": 1742265445,
        "content": [
            {
                "type": "toolResponse",
                "id": "toolu_01BfF7yoP8tv5AM4W4qdVygC",
                "toolResult": {
                    "status": "error",
                    "error": "Execution failed: RPC error: code=-32603, message=Validation Error: Validation Failed\nDetails: {\"message\":\"Validation Failed\",\"errors\":[{\"resource\":\"PullRequest\",\"field\":\"base\",\"code\":\"invalid\"}],\"documentation_url\":\"https://docs.github.com/rest/pulls/pulls#create-a-pull-request\",\"status\":\"422\"}"
                }
            }
        ]
    },

I'll see if I can dig anything up

kalvinnchau avatar Mar 19 '25 21:03 kalvinnchau

I'm also seeing this on v 1.0.15 after using a small tool I wrote. The tool has been working successfully otherwise.

Goose is running! Enter your instructions, or try asking what goose can do.

( O)> Can you generate a react codebase for me?
◐  Measuring response quality...                                                                                          2025-03-26T00:44:55.923356Z ERROR goose::agents::truncate: Error: Request failed: Request failed with status: 400 Bad Request. Message: messages: text content blocks must be non-empty
    at crates/goose/src/agents/truncate.rs:461

Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages: text content blocks must be non-empty.

Please retry if you think this is a transient or recoverable error.
( O)> What time is it?
◒  Scanning information matrices...                                                                                       2025-03-26T00:45:01.789252Z ERROR goose::agents::truncate: Error: Request failed: Request failed with status: 400 Bad Request. Message: messages: text content blocks must be non-empty
    at crates/goose/src/agents/truncate.rs:461

It seems as though Goose gets into a bad state after a tool has been invoked.

nicholasf avatar Mar 26 '25 00:03 nicholasf

Just ran into this also after I tried to stop a task that was running a server and would never exit.

Image

Session file:

{"working_dir":"/Users/zane/Development/mcp_goose_configwatcher","description":"goose config file monitoring","message_count":33,"total_tokens":25939,"input_tokens":25848,"output_tokens":91,"accumulated_total_tokens":277412,"accumulated_input_tokens":271830,"accumulated_output_tokens":5582}
{"role":"user","created":1747178328,"content":[{"type":"text","text":"I have started a basic mcp template and I want to make it so it will alert me when the goose config file changes at /Users/zane/.config/goose/config.yaml so can we have a process that watches this file and sends back the changes to the llm when they happen?"}]}
{"role":"assistant","created":1747178334,"content":[{"type":"text","text":"I'll help you create a file watcher for the Goose config file. Let's break this down into steps:\n\n1. First, let's check the current directory structure to see what we're working with."},{"type":"toolRequest","id":"toolu_bdrk_01H6Vzjip2dzWDWJMQkiwevZ","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"ls -la"}}}}]}
{"role":"user","created":1747178334,"content":[{"type":"toolResponse","id":"toolu_bdrk_01H6Vzjip2dzWDWJMQkiwevZ","toolResult":{"status":"success","value":[{"type":"text","text":"total 32\ndrwxr-xr-x   8 zane  staff   256 May 13 16:13 .\ndrwxr-xr-x  24 zane  staff   768 May 13 16:13 ..\ndrwxr-xr-x   3 zane  staff    96 May 13 16:13 .buildkite\ndrwxr-xr-x@  7 zane  staff   224 May 13 16:13 .idea\n-rw-r--r--   1 zane  staff  1577 May 13 16:13 README.md\n-rw-r--r--   1 zane  staff  1226 May 13 16:13 index.ts\n-rw-r--r--   1 zane  staff   613 May 13 16:13 package.json\n-rw-r--r--   1 zane  staff   367 May 13 16:13 tsconfig.json\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"total 32\ndrwxr-xr-x   8 zane  staff   256 May 13 16:13 .\ndrwxr-xr-x  24 zane  staff   768 May 13 16:13 ..\ndrwxr-xr-x   3 zane  staff    96 May 13 16:13 .buildkite\ndrwxr-xr-x@  7 zane  staff   224 May 13 16:13 .idea\n-rw-r--r--   1 zane  staff  1577 May 13 16:13 README.md\n-rw-r--r--   1 zane  staff  1226 May 13 16:13 index.ts\n-rw-r--r--   1 zane  staff   613 May 13 16:13 package.json\n-rw-r--r--   1 zane  staff   367 May 13 16:13 tsconfig.json\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747178338,"content":[{"type":"text","text":"Let's create a file watcher using Node.js since this is a TypeScript project. We'll use the `chokidar` package for file watching. First, let's install the necessary dependencies:"},{"type":"toolRequest","id":"toolu_bdrk_01MmE6d9zNbZZdKzURaC5tk3","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"npm install chokidar @types/node"}}}}]}
{"role":"user","created":1747178338,"content":[{"type":"toolResponse","id":"toolu_bdrk_01MmE6d9zNbZZdKzURaC5tk3","toolResult":{"status":"success","value":[{"type":"text","text":"npm warn deprecated [email protected]: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.\nnpm warn deprecated [email protected]: Glob versions prior to v9 are no longer supported\n\nadded 103 packages, and audited 104 packages in 5s\n\n16 packages are looking for funding\n  run `npm fund` for details\n\nfound 0 vulnerabilities\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"npm warn deprecated [email protected]: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.\nnpm warn deprecated [email protected]: Glob versions prior to v9 are no longer supported\n\nadded 103 packages, and audited 104 packages in 5s\n\n16 packages are looking for funding\n  run `npm fund` for details\n\nfound 0 vulnerabilities\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747178349,"content":[{"type":"text","text":"Now, let's modify the `index.ts` file to implement the file watcher. First, let's see what's currently in the file:"},{"type":"toolRequest","id":"toolu_bdrk_01VhGgY7xJVLTRqiv2pLFedU","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"view","path":"/Users/zane/Development/mcp_goose_configwatcher/index.ts"}}}}]}
{"role":"user","created":1747178349,"content":[{"type":"toolResponse","id":"toolu_bdrk_01VhGgY7xJVLTRqiv2pLFedU","toolResult":{"status":"success","value":[{"type":"resource","resource":{"uri":"file:///Users/zane/Development/mcp_goose_configwatcher/index.ts","mime_type":"text","text":"import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This is the instruction / prompt for your MCP server. Include instructions on when to use this MCP server and what it can do.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"mcp_ts\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {},\n    },\n    instructions: instructions,\n  }\n);\n\n// Tool for addition\nserver.tool(\n    \"add\", // name\n    \"Adds two numbers\", // description\n    { a: z.number(), b: z.number() }, // params schema\n    { readOnlyHint: true }, // tool annotations\n    async ({ a, b }) => ({\n        content: [{ type: \"text\", text: String(a + b) }],\n    })\n);\n\n\n// Static resource\n// Static resource\nserver.resource(\n  \"config\",\n  \"config://app\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: \"App configuration here\"\n    }]\n  })\n);\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n"},"annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/index.ts\n```typescript\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This is the instruction / prompt for your MCP server. Include instructions on when to use this MCP server and what it can do.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"mcp_ts\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {},\n    },\n    instructions: instructions,\n  }\n);\n\n// Tool for addition\nserver.tool(\n    \"add\", // name\n    \"Adds two numbers\", // description\n    { a: z.number(), b: z.number() }, // params schema\n    { readOnlyHint: true }, // tool annotations\n    async ({ a, b }) => ({\n        content: [{ type: \"text\", text: String(a + b) }],\n    })\n);\n\n\n// Static resource\n// Static resource\nserver.resource(\n  \"config\",\n  \"config://app\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: \"App configuration here\"\n    }]\n  })\n);\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n\n```\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747178364,"content":[{"type":"text","text":"Let's modify this file to implement the config file watcher. We'll:\n1. Add chokidar for file watching\n2. Create a tool that returns the current config content\n3. Set up a resource that will be updated when the config changes\n\nHere's the updated version:"},{"type":"toolRequest","id":"toolu_bdrk_01RJvUzs23XAty6XUuVyG2ti","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"write","file_text":"import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimpimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools to access its content.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {},\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  \n  // Notify the LLM through the resource update\n  server.updateResource('config', 'config://goose', {\n    contents: [{\n      uri: 'config://goose',\n      text: currentConfig\n    }]\n  });\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ type: \"text\", text: currentConfig }],\n  })\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  console.log('Initial config loaded');\n});\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);","path":"/Users/zane/Development/mcp_goose_configwatcher/index.ts"}}}}]}
{"role":"user","created":1747178364,"content":[{"type":"toolResponse","id":"toolu_bdrk_01RJvUzs23XAty6XUuVyG2ti","toolResult":{"status":"success","value":[{"type":"text","text":"Successfully wrote to /Users/zane/Development/mcp_goose_configwatcher/index.ts","annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/index.ts\n```typescript\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools to access its content.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {},\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  \n  // Notify the LLM through the resource update\n  server.updateResource('config', 'config://goose', {\n    contents: [{\n      uri: 'config://goose',\n      text: currentConfig\n    }]\n  });\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ type: \"text\", text: currentConfig }],\n  })\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  console.log('Initial config loaded');\n});\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n```\n","annotations":{"audience":["user"],"priority":0.2}}]}}]}
{"role":"assistant","created":1747178367,"content":[{"type":"text","text":"Now let's update the `package.json` to ensure we have the correct type module setting and scripts:"},{"type":"toolRequest","id":"toolu_bdrk_01GCRpVsfjxm75w1EK2vxz5q","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"view","path":"/Users/zane/Development/mcp_goose_configwatcher/package.json"}}}}]}
{"role":"user","created":1747178367,"content":[{"type":"toolResponse","id":"toolu_bdrk_01GCRpVsfjxm75w1EK2vxz5q","toolResult":{"status":"success","value":[{"type":"resource","resource":{"uri":"file:///Users/zane/Development/mcp_goose_configwatcher/package.json","mime_type":"text","text":"{\n  \"name\": \"@block/mcp_goose_configwatcher\",\n  \"version\": \"0.0.1\",\n  \"description\": \"MCP Server for mcp_goose_configwatcher\",\n  \"license\": \"MIT\",\n  \"author\": \"Block, Inc\",\n  \"homepage\": \"\",\n  \"bugs\": \"\",\n  \"type\": \"module\",\n  \"bin\": {\n    \"mcp_goose_configwatcher\": \"dist/index.js\"\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc && shx chmod +x dist/*.js\",\n    \"prepare\": \"npm run build\",\n    \"watch\": \"tsc --watch\"\n  },\n  \"dependencies\": {\n    \"@modelcontextprotocol/sdk\": \"^1.11.0\",\n    \"chokidar\": \"^4.0.3\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^22.15.17\",\n    \"shx\": \"^0.3.4\",\n    \"typescript\": \"^5.6.2\"\n  }\n}\n"},"annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/package.json\n```json\n{\n  \"name\": \"@block/mcp_goose_configwatcher\",\n  \"version\": \"0.0.1\",\n  \"description\": \"MCP Server for mcp_goose_configwatcher\",\n  \"license\": \"MIT\",\n  \"author\": \"Block, Inc\",\n  \"homepage\": \"\",\n  \"bugs\": \"\",\n  \"type\": \"module\",\n  \"bin\": {\n    \"mcp_goose_configwatcher\": \"dist/index.js\"\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc && shx chmod +x dist/*.js\",\n    \"prepare\": \"npm run build\",\n    \"watch\": \"tsc --watch\"\n  },\n  \"dependencies\": {\n    \"@modelcontextprotocol/sdk\": \"^1.11.0\",\n    \"chokidar\": \"^4.0.3\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^22.15.17\",\n    \"shx\": \"^0.3.4\",\n    \"typescript\": \"^5.6.2\"\n  }\n}\n\n```\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747178370,"content":[{"type":"text","text":"The package.json looks good already. Now let's build and run the server:"},{"type":"toolRequest","id":"toolu_bdrk_015iHbw69b7bn4LmsgFayo6F","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"npm run build"}}}}]}
{"role":"user","created":1747178370,"content":[{"type":"toolResponse","id":"toolu_bdrk_015iHbw69b7bn4LmsgFayo6F","toolResult":{"status":"success","value":[{"type":"text","text":"\n> @block/[email protected] buil> t> tsc && shx chmod +x dist/*.js\n\nindex.ts(56,10): error TS2339: Property 'updateResource' does not exist on type 'McpServer'.\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"\n> @block/[email protected] build\n> tsc && shx chmod +x dist/*.js\n\nindex.ts(56,10): error TS2339: Property 'updateResource' does not exist on type 'McpServer'.\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747178389,"content":[{"type":"text","text":"Ah, I apologize for the error. It seems the `updateResource` method isn't available in the current MCP SDK. Let's modify our approach slightly to use a different method for handling updates. Here's the corrected version:"},{"type":"toolRequest","id":"toolu_bdrk_01NX8eskWWV81bAcRLPcPg1d","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"write","file_text":"import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools to access its content.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {},\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\nlet lastModified = new Date(0);\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  lastModified = new Date();\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ \n      type: \"text\", \n      text: `Last modified: ${lastModified.toISOString()}\\n\\n${currentConfig}` \n    }],\n  })\n);\n\n// Tool to check if config has changed since last check\nserver.tool(\n  \"checkConfigChanged\",\n  \"Checks if the config file has changed since a given timestamp\",\n  { \n    timestamp: z.string().describe(\"ISO timestamp to check against\") \n  },\n  { readOnlyHint: true },\n  async ({ timestamp }) => {\n    const checkTime = new Date(timestamp);\n    const hasChanged = lastModified > checkTime;\n    return {\n      content: [{ \n        type: \"text\", \n        text: hasChanged \n          ? `Config has changed. Last modified: ${lastModified.toISOString()}` \n          : \"No changes since last check\"\n      }],\n    };\n  }\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  lastModified = new Date();\n  console.log('Initial config loaded');\n});\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);","path":"/Users/zane/Development/mcp_goose_configwatcher/index.ts"}}}}]}
{"role":"user","created":1747178389,"content":[{"type":"toolResponse","id":"toolu_bdrk_01NX8eskWWV81bAcRLPcPg1d","toolResult":{"status":"success","value":[{"type":"text","text":"Successfully wrote to /Users/zane/Development/mcp_goose_configwatcher/index.ts","annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/index.ts\n```typescript\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools to access its content.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {},\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\nlet lastModified = new Date(0);\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  lastModified = new Date();\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ \n      type: \"text\", \n      text: `Last modified: ${lastModified.toISOString()}\\n\\n${currentConfig}` \n    }],\n  })\n);\n\n// Tool to check if config has changed since last check\nserver.tool(\n  \"checkConfigChanged\",\n  \"Checks if the config file has changed since a given timestamp\",\n  { \n    timestamp: z.string().describe(\"ISO timestamp to check against\") \n  },\n  { readOnlyHint: true },\n  async ({ timestamp }) => {\n    const checkTime = new Date(timestamp);\n    const hasChanged = lastModified > checkTime;\n    return {\n      content: [{ \n        type: \"text\", \n        text: hasChanged \n          ? `Config has changed. Last modified: ${lastModified.toISOString()}` \n          : \"No changes since last check\"\n      }],\n    };\n  }\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  lastModified = new Date();\n  console.log('Initial config loaded');\n});\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n```\n","annotations":{"audience":["user"],"priority":0.2}}]}}]}
{"role":"user","created":1747179723,"content":[{"type":"text","text":"I updated the mcp sdk to version 1.11.2 can you look at node_modules/@modelcontextprotocol/sdk/dist/esm/types.js to see what is available?"}]}
{"role":"assistant","created":1747179727,"content":[{"type":"text","text":"I'll check the SDK types to see what's available:"},{"type":"toolRequest","id":"toolu_bdrk_01RfgTWLbSugg4KcfhWeEkmW","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"ls -la node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"}}}}]}
{"role":"user","created":1747179727,"content":[{"type":"toolResponse","id":"toolu_bdrk_01RfgTWLbSugg4KcfhWeEkmW","toolResult":{"status":"success","value":[{"type":"text","text":"-rw-r--r--  1 zane  staff  35731 May 13 16:19 node_modules/@modelcontextprotocol/sdk/dist/esm/types.js\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"-rw-r--r--  1 zane  staff  35731 May 13 16:19 node_modules/@modelcontextprotocol/sdk/dist/esm/types.js\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747179731,"content":[{"type":"text","text":""},{"type":"toolRequest","id":"toolu_bdrk_01NyPUDNLab23QgT5725Ewsh","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"view","path":"/Users/zane/Development/mcp_goose_configwatcher/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"}}}}]}
{"role":"user","created":1747179731,"content":[{"type":"toolResponse","id":"toolu_bdrk_01NyPUDNLab23QgT5725Ewsh","toolResult":{"status":"success","value":[{"type":"resource","resource":{"uri":"file:///Users/zane/Development/mcp_goose_configwatcher/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js","mime_type":"text","text":"import { z } from \"zod\";\nexport const LATEST_PROTOCOL_VERSION = \"2025-03-26\";\nexport const SUPPORTED_PROTOCOL_VERSIONS = [\n    LATEST_PROTOCOL_VERSION,\n    \"2024-11-05\",\n    \"2024-10-07\",\n];\n/* JSON-RPC types */\nexport const JSONRPC_VERSION = \"2.0\";\n/**\n * A progress token, used to associate progress notifications with the original request.\n */\nexport const ProgressTokenSchema = z.union([z.string(), z.number().int()]);\n/**\n * An opaque token used to represent a cursor for pagination.\n */\nexport const CursorSchema = z.string();\nconst RequestMetaSchema = z\n    .object({\n    /**\n     * If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.\n     */\n    progressToken: z.optional(ProgressTokenSchema),\n})\n    .passthrough();\nconst BaseRequestParamsSchema = z\n    .object({\n    _meta: z.optional(RequestMetaSchema),\n})\n    .passthrough();\nexport const RequestSchema = z.object({\n    method: z.string(),\n    params: z.optional(BaseRequestParamsSchema),\n});\nconst BaseNotificationParamsSchema = z\n    .object({\n    /**\n     * This parameter name is reserved by MCP to allow clients and servers to attach additional metadata to their notifications.\n     */\n    _meta: z.optional(z.object({}).passthrough()),\n})\n    .passthrough();\nexport const NotificationSchema = z.object({\n    method: z.string(),\n    params: z.optional(BaseNotificationParamsSchema),\n});\nexport const ResultSchema = z\n    .object({\n    /**\n     * This result property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses.\n     */\n    _meta: z.optional(z.object({}).passthrough()),\n})\n    .passthrough();\n/**\n * A uniquely identifying ID for a request in JSON-RPC.\n */\nexport const RequestIdSchema = z.union([z.string(), z.number().int()]);\n/**\n * A request that expects a response.\n */\nexport const JSONRPCRequestSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n    id: RequestIdSchema,\n})\n    .merge(RequestSchema)\n    .strict();\nexport const isJSONRPCRequest = (value) => JSONRPCRequestSchema.safeParse(value).success;\n/**\n * A notification which does not expect a response.\n */\nexport const JSONRPCNotificationSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n})\n    .merge(NotificationSchema)\n    .strict();\nexport const isJSONRPCNotification = (value) => JSONRPCNotificationSchema.safeParse(value).success;\n/**\n * A successful (non-error) response to a request.\n */\nexport const JSONRPCResponseSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n    id: RequestIdSchema,\n    result: ResultSchema,\n})\n    .strict();\nexport const isJSONRPCResponse = (value) => JSONRPCResponseSchema.safeParse(value).success;\n/**\n * Error codes defined by the JSON-RPC specification.\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n    // SDK error codes\n    ErrorCode[ErrorCode[\"ConnectionClosed\"] = -32000] = \"ConnectionClosed\";\n    ErrorCode[ErrorCode[\"RequestTimeout\"] = -32001] = \"RequestTimeout\";\n    // Standard JSON-RPC error codes\n    ErrorCode[ErrorCode[\"ParseError\"] = -32700] = \"ParseError\";\n    ErrorCode[ErrorCode[\"InvalidRequest\"] = -32600] = \"InvalidRequest\";\n    ErrorCode[ErrorCode[\"MethodNotFound\"] = -32601] = \"MethodNotFound\";\n    ErrorCode[ErrorCode[\"InvalidParams\"] = -32602] = \"InvalidParams\";\n    ErrorCode[ErrorCode[\"InternalError\"] = -32603] = \"InternalError\";\n})(ErrorCode || (ErrorCode = {}));\n/**\n * A response to a request that indicates an error occurred.\n */\nexport const JSONRPCErrorSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n    id: RequestIdSchema,\n    error: z.object({\n        /**\n         * The error type that occurred.\n         */\n        code: z.number().int(),\n        /**\n         * A short description of the error. The message SHOULD be limited to a concise single sentence.\n         */\n        message: z.string(),\n        /**\n         * Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).\n         */\n        data: z.optional(z.unknown()),\n    }),\n})\n    .strict();\nexport const isJSONRPCError = (value) => JSONRPCErrorSchema.safeParse(value).success;\nexport const JSONRPCMessageSchema = z.union([\n    JSONRPCRequestSchema,\n    JSONRPCNotificationSchema,\n    JSONRPCResponseSchema,\n    JSONRPCErrorSchema,\n]);\n/* Empty result */\n/**\n * A response that indicates success but carries no data.\n */\nexport const EmptyResultSchema = ResultSchema.strict();\n/* Cancellation */\n/**\n * This notification can be sent by either side to indicate that it is cancelling a previously-issued request.\n *\n * The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n *\n * This notification indicates that the result will be unused, so any associated processing SHOULD cease.\n *\n * A client MUST NOT attempt to cancel its `initialize` request.\n */\nexport const CancelledNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/cancelled\"),\n    params: BaseNotificationParamsSchema.extend({\n        /**\n         * The ID of the request to cancel.\n         *\n         * This MUST correspond to the ID of a request previously issued in the same direction.\n         */\n        requestId: RequestIdSchema,\n        /**\n         * An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.\n         */\n        reason: z.string().optional(),\n    }),\n});\n/* Initialization */\n/**\n * Describes the name and version of an MCP implementation.\n */\nexport const ImplementationSchema = z\n    .object({\n    name: z.string(),\n    version: z.string(),\n})\n    .passthrough();\n/**\n * Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.\n */\nexport const ClientCapabilitiesSchema = z\n    .object({\n    /**\n     * Experimental, non-standard capabilities that the client supports.\n     */\n    experimental: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the client supports sampling from an LLM.\n     */\n    sampling: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the client supports listing roots.\n     */\n    roots: z.optional(z\n        .object({\n        /**\n         * Whether the client supports issuing notifications for changes to the roots list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n})\n    .passthrough();\n/**\n * This request is sent from the client to the server when it first connects, asking it to begin initialization.\n */\nexport const InitializeRequestSchema = RequestSchema.extend({\n    method: z.literal(\"initialize\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well.\n         */\n        protocolVersion: z.string(),\n        capabilities: ClientCapabilitiesSchema,\n        clientInfo: ImplementationSchema,\n    }),\n});\nexport const isInitializeRequest = (value) => InitializeRequestSchema.safeParse(value).success;\n/**\n * Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.\n */\nexport const ServerCapabilitiesSchema = z\n    .object({\n    /**\n     * Experimental, non-standard capabilities that the server supports.\n     */\n    experimental: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the server supports sending log messages to the client.\n     */\n    logging: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the server supports sending completions to the client.\n     */\n    completions: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the server offers any prompt templates.\n     */\n    prompts: z.optional(z\n        .object({\n        /**\n         * Whether this server supports issuing notifications for changes to the prompt list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n    /**\n     * Present if the server offers any resources to read.\n     */\n    resources: z.optional(z\n        .object({\n        /**\n         * Whether this server supports clients subscribing to resource updates.\n         */\n        subscribe: z.optional(z.boolean()),\n        /**\n         * Whether this server supports issuing notifications for changes to the resource list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n    /**\n     * Present if the server offers any tools to call.\n     */\n    tools: z.optional(z\n        .object({\n        /**\n         * Whether this server supports issuing notifications for changes to the tool list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n})\n    .passthrough();\n/**\n * After receiving an initialize request from the client, the server sends this response.\n */\nexport const InitializeResultSchema = ResultSchema.extend({\n    /**\n     * The version of the Model Context Protocol that the server wants to use. This may not match the version that the client requested. If the client cannot support this version, it MUST disconnect.\n     */\n    protocolVersion: z.string(),\n    capabilities: ServerCapabilitiesSchema,\n    serverInfo: ImplementationSchema,\n    /**\n     * Instructions describing how to use the server and its features.\n     *\n     * This can be used by clients to improve the LLM's understanding of available tools, resources, etc. It can be thought of like a \"hint\" to the model. For example, this information MAY be added to the system prompt.\n     */\n    instructions: z.optional(z.string()),\n});\n/**\n * This notification is sent from the client to the server after initialization has finished.\n */\nexport const InitializedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/initialized\"),\n});\nexport const isInitializedNotification = (value) => InitializedNotificationSchema.safeParse(value).success;\n/* Ping */\n/**\n * A ping, issued by either the server or the client, to check that the other party is still alive. The receiver must promptly respond, or else may be disconnected.\n */\nexport const PingRequestSchema = RequestSchema.extend({\n    method: z.literal(\"ping\"),\n});\n/* Progress notifications */\nexport const ProgressSchema = z\n    .object({\n    /**\n     * The progress thus far. This should increase every time progress is made, even if the total is unknown.\n     */\n    progress: z.number(),\n    /**\n     * Total number of items to process (or total progress required), if known.\n     */\n    total: z.optional(z.number()),\n})\n    .passthrough();\n/**\n * An out-of-band notification used to inform the receiver of a progress update for a long-running request.\n */\nexport const ProgressNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/progress\"),\n    params: BaseNotificationParamsSchema.merge(ProgressSchema).extend({\n        /**\n         * The progress token which was given in the initial request, used to associate this notification with the request that is proceeding.\n         */\n        progressToken: ProgressTokenSchema,\n    }),\n});\n/* Pagination */\nexport const PaginatedRequestSchema = RequestSchema.extend({\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * An opaque token representing the current pagination position.\n         * If provided, the server should return results starting after this cursor.\n         */\n        cursor: z.optional(CursorSchema),\n    }).optional(),\n});\nexport const PaginatedResultSchema = ResultSchema.extend({\n    /**\n     * An opaque token representing the pagination position after the last returned result.\n     * If present, there may be more results available.\n     */\n    nextCursor: z.optional(CursorSchema),\n});\n/* Resources */\n/**\n * The contents of a specific resource or sub-resource.\n */\nexport const ResourceContentsSchema = z\n    .object({\n    /**\n     * The URI of this resource.\n     */\n    uri: z.string(),\n    /**\n     * The MIME type of this resource, if known.\n     */\n    mimeType: z.optional(z.string()),\n})\n    .passthrough();\nexport const TextResourceContentsSchema = ResourceContentsSchema.extend({\n    /**\n     * The text of the item. This must only be set if the item can actually be represented as text (not binary data).\n     */\n    text: z.string(),\n});\nexport const BlobResourceContentsSchema = ResourceContentsSchema.extend({\n    /**\n     * A base64-encoded string representing the binary data of the item.\n     */\n    blob: z.string().base64(),\n});\n/**\n * A known resource that the server is capable of reading.\n */\nexport const ResourceSchema = z\n    .object({\n    /**\n     * The URI of this resource.\n     */\n    uri: z.string(),\n    /**\n     * A human-readable name for this resource.\n     *\n     * This can be used by clients to populate UI elements.\n     */\n    name: z.string(),\n    /**\n     * A description of what this resource represents.\n     *\n     * This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a \"hint\" to the model.\n     */\n    description: z.optional(z.string()),\n    /**\n     * The MIME type of this resource, if known.\n     */\n    mimeType: z.optional(z.string()),\n})\n    .passthrough();\n/**\n * A template description for resources available on the server.\n */\nexport const ResourceTemplateSchema = z\n    .object({\n    /**\n     * A URI template (according to RFC 6570) that can be used to construct resource URIs.\n     */\n    uriTemplate: z.string(),\n    /**\n     * A human-readable name for the type of resource this template refers to.\n     *\n     * This can be used by clients to populate UI elements.\n     */\n    name: z.string(),\n    /**\n     * A description of what this template is for.\n     *\n     * This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a \"hint\" to the model.\n     */\n    description: z.optional(z.string()),\n    /**\n     * The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type.\n     */\n    mimeType: z.optional(z.string()),\n})\n    .passthrough();\n/**\n * Sent from the client to request a list of resources the server has.\n */\nexport const ListResourcesRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"resources/list\"),\n});\n/**\n * The server's response to a resources/list request from the client.\n */\nexport const ListResourcesResultSchema = PaginatedResultSchema.extend({\n    resources: z.array(ResourceSchema),\n});\n/**\n * Sent from the client to request a list of resource templates the server has.\n */\nexport const ListResourceTemplatesRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"resources/templates/list\"),\n});\n/**\n * The server's response to a resources/templates/list request from the client.\n */\nexport const ListResourceTemplatesResultSchema = PaginatedResultSchema.extend({\n    resourceTemplates: z.array(ResourceTemplateSchema),\n});\n/**\n * Sent from the client to the server, to read a specific resource URI.\n */\nexport const ReadResourceRequestSchema = RequestSchema.extend({\n    method: z.literal(\"resources/read\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The URI of the resource to read. The URI can use any protocol; it is up to the server how to interpret it.\n         */\n        uri: z.string(),\n    }),\n});\n/**\n * The server's response to a resources/read request from the client.\n */\nexport const ReadResourceResultSchema = ResultSchema.extend({\n    contents: z.array(z.union([TextResourceContentsSchema, BlobResourceContentsSchema])),\n});\n/**\n * An optional notification from the server to the client, informing it that the list of resources it can read from has changed. This may be issued by servers without any previous subscription from the client.\n */\nexport const ResourceListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/resources/list_changed\"),\n});\n/**\n * Sent from the client to request resources/updated notifications from the server whenever a particular resource changes.\n */\nexport const SubscribeRequestSchema = RequestSchema.extend({\n    method: z.literal(\"resources/subscribe\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The URI of the resource to subscribe to. The URI can use any protocol; it is up to the server how to interpret it.\n         */\n        uri: z.string(),\n    }),\n});\n/**\n * Sent from the client to request cancellation of resources/updated notifications from the server. This should follow a previous resources/subscribe request.\n */\nexport const UnsubscribeRequestSchema = RequestSchema.extend({\n    method: z.literal(\"resources/unsubscribe\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The URI of the resource to unsubscribe from.\n         */\n        uri: z.string(),\n    }),\n});\n/**\n * A notification from the server to the client, informing it that a resource has changed and may need to be read again. This should only be sent if the client previously sent a resources/subscribe request.\n */\nexport const ResourceUpdatedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/resources/updated\"),\n    params: BaseNotificationParamsSchema.extend({\n        /**\n         * The URI of the resource that has been updated. This might be a sub-resource of the one that the client actually subscribed to.\n         */\n        uri: z.string(),\n    }),\n});\n/* Prompts */\n/**\n * Describes an argument that a prompt can accept.\n */\nexport const PromptArgumentSchema = z\n    .object({\n    /**\n     * The name of the argument.\n     */\n    name: z.string(),\n    /**\n     * A human-readable description of the argument.\n     */\n    description: z.optional(z.string()),\n    /**\n     * Whether this argument must be provided.\n     */\n    required: z.optional(z.boolean()),\n})\n    .passthrough();\n/**\n * A prompt or prompt template that the server offers.\n */\nexport const PromptSchema = z\n    .object({\n    /**\n     * The name of the prompt or prompt template.\n     */\n    name: z.string(),\n    /**\n     * An optional description of what this prompt provides\n     */\n    description: z.optional(z.string()),\n    /**\n     * A list of arguments to use for templating the prompt.\n     */\n    arguments: z.optional(z.array(PromptArgumentSchema)),\n})\n    .passthrough();\n/**\n * Sent from the client to request a list of prompts and prompt templates the server has.\n */\nexport const ListPromptsRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"prompts/list\"),\n});\n/**\n * The server's response to a prompts/list request from the client.\n */\nexport const ListPromptsResultSchema = PaginatedResultSchema.extend({\n    prompts: z.array(PromptSchema),\n});\n/**\n * Used by the client to get a prompt provided by the server.\n */\nexport const GetPromptRequestSchema = RequestSchema.extend({\n    method: z.literal(\"prompts/get\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The name of the prompt or prompt template.\n         */\n        name: z.string(),\n        /**\n         * Arguments to use for templating the prompt.\n         */\n        arguments: z.optional(z.record(z.string())),\n    }),\n});\n/**\n * Text provided to or from an LLM.\n */\nexport const TextContentSchema = z\n    .object({\n    type: z.literal(\"text\"),\n    /**\n     * The text content of the message.\n     */\n    text: z.string(),\n})\n    .passthrough();\n/**\n * An image provided to or from an LLM.\n */\nexport const ImageContentSchema = z\n    .object({\n    type: z.literal(\"image\"),\n    /**\n     * The base64-encoded image data.\n     */\n    data: z.string().base64(),\n    /**\n     * The MIME type of the image. Different providers may support different image types.\n     */\n    mimeType: z.string(),\n})\n    .passthrough();\n/**\n * An Audio provided to or from an LLM.\n */\nexport const AudioContentSchema = z\n    .object({\n    type: z.literal(\"audio\"),\n    /**\n     * The base64-encoded audio data.\n     */\n    data: z.string().base64(),\n    /**\n     * The MIME type of the audio. Different providers may support different audio types.\n     */\n    mimeType: z.string(),\n})\n    .passthrough();\n/**\n * The contents of a resource, embedded into a prompt or tool call result.\n */\nexport const EmbeddedResourceSchema = z\n    .object({\n    type: z.literal(\"resource\"),\n    resource: z.union([TextResourceContentsSchema, BlobResourceContentsSchema]),\n})\n    .passthrough();\n/**\n * Describes a message returned as part of a prompt.\n */\nexport const PromptMessageSchema = z\n    .object({\n    role: z.enum([\"user\", \"assistant\"]),\n    content: z.union([\n        TextContentSchema,\n        ImageContentSchema,\n        AudioContentSchema,\n        EmbeddedResourceSchema,\n    ]),\n})\n    .passthrough();\n/**\n * The server's response to a prompts/get request from the client.\n */\nexport const GetPromptResultSchema = ResultSchema.extend({\n    /**\n     * An optional description for the prompt.\n     */\n    description: z.optional(z.string()),\n    messages: z.array(PromptMessageSchema),\n});\n/**\n * An optional notification from the server to the client, informing it that the list of prompts it offers has changed. This may be issued by servers without any previous subscription from the client.\n */\nexport const PromptListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/prompts/list_changed\"),\n});\n/* Tools */\n/**\n * Additional properties describing a Tool to clients.\n *\n * NOTE: all properties in ToolAnnotations are **hints**.\n * They are not guaranteed to provide a faithful description of\n * tool behavior (including descriptive properties like `title`).\n *\n * Clients should never make tool use decisions based on ToolAnnotations\n * received from untrusted servers.\n */\nexport const ToolAnnotationsSchema = z\n    .object({\n    /**\n     * A human-readable title for the tool.\n     */\n    title: z.optional(z.string()),\n    /**\n     * If true, the tool does not modify its environment.\n     *\n     * Default: false\n     */\n    readOnlyHint: z.optional(z.boolean()),\n    /**\n     * If true, the tool may perform destructive updates to its environment.\n     * If false, the tool performs only additive updates.\n     *\n     * (This property is meaningful only when `readOnlyHint == false`)\n     *\n     * Default: true\n     */\n    destructiveHint: z.optional(z.boolean()),\n    /**\n     * If true, calling the tool repeatedly with the same arguments\n     * will have no additional effect on the its environment.\n     *\n     * (This property is meaningful only when `readOnlyHint == false`)\n     *\n     * Default: false\n     */\n    idempotentHint: z.optional(z.boolean()),\n    /**\n     * If true, this tool may interact with an \"open world\" of external\n     * entities. If false, the tool's domain of interaction is closed.\n     * For example, the world of a web search tool is open, whereas that\n     * of a memory tool is not.\n     *\n     * Default: true\n     */\n    openWorldHint: z.optional(z.boolean()),\n})\n    .passthrough();\n/**\n * Definition for a tool the client can call.\n */\nexport const ToolSchema = z\n    .object({\n    /**\n     * The name of the tool.\n     */\n    name: z.string(),\n    /**\n     * A human-readable description of the tool.\n     */\n    description: z.optional(z.string()),\n    /**\n     * A JSON Schema object defining the expected parameters for the tool.\n     */\n    inputSchema: z\n        .object({\n        type: z.literal(\"object\"),\n        properties: z.optional(z.object({}).passthrough()),\n    })\n        .passthrough(),\n    /**\n     * Optional additional tool information.\n     */\n    annotations: z.optional(ToolAnnotationsSchema),\n})\n    .passthrough();\n/**\n * Sent from the client to request a list of tools the server has.\n */\nexport const ListToolsRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"tools/list\"),\n});\n/**\n * The server's response to a tools/list request from the client.\n */\nexport const ListToolsResultSchema = PaginatedResultSchema.extend({\n    tools: z.array(ToolSchema),\n});\n/**\n * The server's response to a tool call.\n */\nexport const CallToolResultSchema = ResultSchema.extend({\n    content: z.array(z.union([TextContentSchema, ImageContentSchema, AudioContentSchema, EmbeddedResourceSchema])),\n    isError: z.boolean().default(false).optional(),\n});\n/**\n * CallToolResultSchema extended with backwards compatibility to protocol version 2024-10-07.\n */\nexport const CompatibilityCallToolResultSchema = CallToolResultSchema.or(ResultSchema.extend({\n    toolResult: z.unknown(),\n}));\n/**\n * Used by the client to invoke a tool provided by the server.\n */\nexport const CallToolRequestSchema = RequestSchema.extend({\n    method: z.literal(\"tools/call\"),\n    params: BaseRequestParamsSchema.extend({\n        name: z.string(),\n        arguments: z.optional(z.record(z.unknown())),\n    }),\n});\n/**\n * An optional notification from the server to the client, informing it that the list of tools it offers has changed. This may be issued by servers without any previous subscription from the client.\n */\nexport const ToolListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/tools/list_changed\"),\n});\n/* Logging */\n/**\n * The severity of a log message.\n */\nexport const LoggingLevelSchema = z.enum([\n    \"debug\",\n    \"info\",\n    \"notice\",\n    \"warning\",\n    \"error\",\n    \"critical\",\n    \"alert\",\n    \"emergency\",\n]);\n/**\n * A request from the client to the server, to enable or adjust logging.\n */\nexport const SetLevelRequestSchema = RequestSchema.extend({\n    method: z.literal(\"logging/setLevel\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The level of logging that the client wants to receive from the server. The server should send all logs at this level and higher (i.e., more severe) to the client as notifications/logging/message.\n         */\n        level: LoggingLevelSchema,\n    }),\n});\n/**\n * Notification of a log message passed from server to client. If no logging/setLevel request has been sent from the client, the server MAY decide which messages to send automatically.\n */\nexport const LoggingMessageNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/message\"),\n    params: BaseNotificationParamsSchema.extend({\n        /**\n         * The severity of this log message.\n         */\n        level: LoggingLevelSchema,\n        /**\n         * An optional name of the logger issuing this message.\n         */\n        logger: z.optional(z.string()),\n        /**\n         * The data to be logged, such as a string message or an object. Any JSON serializable type is allowed here.\n         */\n        data: z.unknown(),\n    }),\n});\n/* Sampling */\n/**\n * Hints to use for model selection.\n */\nexport const ModelHintSchema = z\n    .object({\n    /**\n     * A hint for a model name.\n     */\n    name: z.string().optional(),\n})\n    .passthrough();\n/**\n * The server's preferences for model selection, requested of the client during sampling.\n */\nexport const ModelPreferencesSchema = z\n    .object({\n    /**\n     * Optional hints to use for model selection.\n     */\n    hints: z.optional(z.array(ModelHintSchema)),\n    /**\n     * How much to prioritize cost when selecting a model.\n     */\n    costPriority: z.optional(z.number().min(0).max(1)),\n    /**\n     * How much to prioritize sampling speed (latency) when selecting a model.\n     */\n    speedPriority: z.optional(z.number().min(0).max(1)),\n    /**\n     * How much to prioritize intelligence and capabilities when selecting a model.\n     */\n    intelligencePriority: z.optional(z.number().min(0).max(1)),\n})\n    .passthrough();\n/**\n * Describes a message issued to or received from an LLM API.\n */\nexport const SamplingMessageSchema = z\n    .object({\n    role: z.enum([\"user\", \"assistant\"]),\n    content: z.union([TextContentSchema, ImageContentSchema, AudioContentSchema]),\n})\n    .passthrough();\n/**\n * A request from the server to sample an LLM via the client. The client has full discretion over which model to select. The client should also inform the user before beginning sampling, to allow them to inspect the request (human in the loop) and decide whether to approve it.\n */\nexport const CreateMessageRequestSchema = RequestSchema.extend({\n    method: z.literal(\"sampling/createMessage\"),\n    params: BaseRequestParamsSchema.extend({\n        messages: z.array(SamplingMessageSchema),\n        /**\n         * An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.\n         */\n        systemPrompt: z.optional(z.string()),\n        /**\n         * A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.\n         */\n        includeContext: z.optional(z.enum([\"none\", \"thisServer\", \"allServers\"])),\n        temperature: z.optional(z.number()),\n        /**\n         * The maximum number of tokens to sample, as requested by the server. The client MAY choose to sample fewer tokens than requested.\n         */\n        maxTokens: z.number().int(),\n        stopSequences: z.optional(z.array(z.string())),\n        /**\n         * Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.\n         */\n        metadata: z.optional(z.object({}).passthrough()),\n        /**\n         * The server's preferences for which model to select.\n         */\n        modelPreferences: z.optional(ModelPreferencesSchema),\n    }),\n});\n/**\n * The client's response to a sampling/create_message request from the server. The client should inform the user before returning the sampled message, to allow them to inspect the response (human in the loop) and decide whether to allow the server to see it.\n */\nexport const CreateMessageResultSchema = ResultSchema.extend({\n    /**\n     * The name of the model that generated the message.\n     */\n    model: z.string(),\n    /**\n     * The reason why sampling stopped.\n     */\n    stopReason: z.optional(z.enum([\"endTurn\", \"stopSequence\", \"maxTokens\"]).or(z.string())),\n    role: z.enum([\"user\", \"assistant\"]),\n    content: z.discriminatedUnion(\"type\", [\n        TextContentSchema,\n        ImageContentSchema,\n        AudioContentSchema\n    ]),\n});\n/* Autocomplete */\n/**\n * A reference to a resource or resource template definition.\n */\nexport const ResourceReferenceSchema = z\n    .object({\n    type: z.literal(\"ref/resource\"),\n    /**\n     * The URI or URI template of the resource.\n     */\n    uri: z.string(),\n})\n    .passthrough();\n/**\n * Identifies a prompt.\n */\nexport const PromptReferenceSchema = z\n    .object({\n    type: z.literal(\"ref/prompt\"),\n    /**\n     * The name of the prompt or prompt template\n     */\n    name: z.string(),\n})\n    .passthrough();\n/**\n * A request from the client to the server, to ask for completion options.\n */\nexport const CompleteRequestSchema = RequestSchema.extend({\n    method: z.literal(\"completion/complete\"),\n    params: BaseRequestParamsSchema.extend({\n        ref: z.union([PromptReferenceSchema, ResourceReferenceSchema]),\n        /**\n         * The argument's information\n         */\n        argument: z\n            .object({\n            /**\n             * The name of the argument\n             */\n            name: z.string(),\n            /**\n             * The value of the argument to use for completion matching.\n             */\n            value: z.string(),\n        })\n            .passthrough(),\n    }),\n});\n/**\n * The server's response to a completion/complete request\n */\nexport const CompleteResultSchema = ResultSchema.extend({\n    completion: z\n        .object({\n        /**\n         * An array of completion values. Must not exceed 100 items.\n         */\n        values: z.array(z.string()).max(100),\n        /**\n         * The total number of completion options available. This can exceed the number of values actually sent in the response.\n         */\n        total: z.optional(z.number().int()),\n        /**\n         * Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.\n         */\n        hasMore: z.optional(z.boolean()),\n    })\n        .passthrough(),\n});\n/* Roots */\n/**\n * Represents a root directory or file that the server can operate on.\n */\nexport const RootSchema = z\n    .object({\n    /**\n     * The URI identifying the root. This *must* start with file:// for now.\n     */\n    uri: z.string().startsWith(\"file://\"),\n    /**\n     * An optional name for the root.\n     */\n    name: z.optional(z.string()),\n})\n    .passthrough();\n/**\n * Sent from the server to request a list of root URIs from the client.\n */\nexport const ListRootsRequestSchema = RequestSchema.extend({\n    method: z.literal(\"roots/list\"),\n});\n/**\n * The client's response to a roots/list request from the server.\n */\nexport const ListRootsResultSchema = ResultSchema.extend({\n    roots: z.array(RootSchema),\n});\n/**\n * A notification from the client to the server, informing it that the list of roots has changed.\n */\nexport const RootsListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/roots/list_changed\"),\n});\n/* Client messages */\nexport const ClientRequestSchema = z.union([\n    PingRequestSchema,\n    InitializeRequestSchema,\n    CompleteRequestSchema,\n    SetLevelRequestSchema,\n    GetPromptRequestSchema,\n    ListPromptsRequestSchema,\n    ListResourcesRequestSchema,\n    ListResourceTemplatesRequestSchema,\n    ReadResourceRequestSchema,\n    SubscribeRequestSchema,\n    UnsubscribeRequestSchema,\n    CallToolRequestSchema,\n    ListToolsRequestSchema,\n]);\nexport const ClientNotificationSchema = z.union([\n    CancelledNotificationSchema,\n    ProgressNotificationSchema,\n    InitializedNotificationSchema,\n    RootsListChangedNotificationSchema,\n]);\nexport const ClientResultSchema = z.union([\n    EmptyResultSchema,\n    CreateMessageResultSchema,\n    ListRootsResultSchema,\n]);\n/* Server messages */\nexport const ServerRequestSchema = z.union([\n    PingRequestSchema,\n    CreateMessageRequestSchema,\n    ListRootsRequestSchema,\n]);\nexport const ServerNotificationSchema = z.union([\n    CancelledNotificationSchema,\n    ProgressNotificationSchema,\n    LoggingMessageNotificationSchema,\n    ResourceUpdatedNotificationSchema,\n    ResourceListChangedNotificationSchema,\n    ToolListChangedNotificationSchema,\n    PromptListChangedNotificationSchema,\n]);\nexport const ServerResultSchema = z.union([\n    EmptyResultSchema,\n    InitializeResultSchema,\n    CompleteResultSchema,\n    GetPromptResultSchema,\n    ListPromptsResultSchema,\n    ListResourcesResultSchema,\n    ListResourceTemplatesResultSchema,\n    ReadResourceResultSchema,\n    CallToolResultSchema,\n    ListToolsResultSchema,\n]);\nexport class McpError extends Error {\n    constructor(code, message, data) {\n        super(`MCP error ${code}: ${message}`);\n        this.code = code;\n        this.data = data;\n        this.name = \"McpError\";\n    }\n}\n//# sourceMappingURL=types.js.map"},"annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js\n```javascript\nimport { z } from \"zod\";\nexport const LATEST_PROTOCOL_VERSION = \"2025-03-26\";\nexport const SUPPORTED_PROTOCOL_VERSIONS = [\n    LATEST_PROTOCOL_VERSION,\n    \"2024-11-05\",\n    \"2024-10-07\",\n];\n/* JSON-RPC types */\nexport const JSONRPC_VERSION = \"2.0\";\n/**\n * A progress token, used to associate progress notifications with the original request.\n */\nexport const ProgressTokenSchema = z.union([z.string(), z.number().int()]);\n/**\n * An opaque token used to represent a cursor for pagination.\n */\nexport const CursorSchema = z.string();\nconst RequestMetaSchema = z\n    .object({\n    /**\n     * If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.\n     */\n    progressToken: z.optional(ProgressTokenSchema),\n})\n    .passthrough();\nconst BaseRequestParamsSchema = z\n    .object({\n    _meta: z.optional(RequestMetaSchema),\n})\n    .passthrough();\nexport const RequestSchema = z.object({\n    method: z.string(),\n    params: z.optional(BaseRequestParamsSchema),\n});\nconst BaseNotificationParamsSchema = z\n    .object({\n    /**\n     * This parameter name is reserved by MCP to allow clients and servers to attach additional metadata to their notifications.\n     */\n    _meta: z.optional(z.object({}).passthrough()),\n})\n    .passthrough();\nexport const NotificationSchema = z.object({\n    method: z.string(),\n    params: z.optional(BaseNotificationParamsSchema),\n});\nexport const ResultSchema = z\n    .object({\n    /**\n     * This result property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses.\n     */\n    _meta: z.optional(z.object({}).passthrough()),\n})\n    .passthrough();\n/**\n * A uniquely identifying ID for a request in JSON-RPC.\n */\nexport const RequestIdSchema = z.union([z.string(), z.number().int()]);\n/**\n * A request that expects a response.\n */\nexport const JSONRPCRequestSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n    id: RequestIdSchema,\n})\n    .merge(RequestSchema)\n    .strict();\nexport const isJSONRPCRequest = (value) => JSONRPCRequestSchema.safeParse(value).success;\n/**\n * A notification which does not expect a response.\n */\nexport const JSONRPCNotificationSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n})\n    .merge(NotificationSchema)\n    .strict();\nexport const isJSONRPCNotification = (value) => JSONRPCNotificationSchema.safeParse(value).success;\n/**\n * A successful (non-error) response to a request.\n */\nexport const JSONRPCResponseSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n    id: RequestIdSchema,\n    result: ResultSchema,\n})\n    .strict();\nexport const isJSONRPCResponse = (value) => JSONRPCResponseSchema.safeParse(value).success;\n/**\n * Error codes defined by the JSON-RPC specification.\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n    // SDK error codes\n    ErrorCode[ErrorCode[\"ConnectionClosed\"] = -32000] = \"ConnectionClosed\";\n    ErrorCode[ErrorCode[\"RequestTimeout\"] = -32001] = \"RequestTimeout\";\n    // Standard JSON-RPC error codes\n    ErrorCode[ErrorCode[\"ParseError\"] = -32700] = \"ParseError\";\n    ErrorCode[ErrorCode[\"InvalidRequest\"] = -32600] = \"InvalidRequest\";\n    ErrorCode[ErrorCode[\"MethodNotFound\"] = -32601] = \"MethodNotFound\";\n    ErrorCode[ErrorCode[\"InvalidParams\"] = -32602] = \"InvalidParams\";\n    ErrorCode[ErrorCode[\"InternalError\"] = -32603] = \"InternalError\";\n})(ErrorCode || (ErrorCode = {}));\n/**\n * A response to a request that indicates an error occurred.\n */\nexport const JSONRPCErrorSchema = z\n    .object({\n    jsonrpc: z.literal(JSONRPC_VERSION),\n    id: RequestIdSchema,\n    error: z.object({\n        /**\n         * The error type that occurred.\n         */\n        code: z.number().int(),\n        /**\n         * A short description of the error. The message SHOULD be limited to a concise single sentence.\n         */\n        message: z.string(),\n        /**\n         * Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).\n         */\n        data: z.optional(z.unknown()),\n    }),\n})\n    .strict();\nexport const isJSONRPCError = (value) => JSONRPCErrorSchema.safeParse(value).success;\nexport const JSONRPCMessageSchema = z.union([\n    JSONRPCRequestSchema,\n    JSONRPCNotificationSchema,\n    JSONRPCResponseSchema,\n    JSONRPCErrorSchema,\n]);\n/* Empty result */\n/**\n * A response that indicates success but carries no data.\n */\nexport const EmptyResultSchema = ResultSchema.strict();\n/* Cancellation */\n/**\n * This notification can be sent by either side to indicate that it is cancelling a previously-issued request.\n *\n * The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n *\n * This notification indicates that the result will be unused, so any associated processing SHOULD cease.\n *\n * A client MUST NOT attempt to cancel its `initialize` request.\n */\nexport const CancelledNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/cancelled\"),\n    params: BaseNotificationParamsSchema.extend({\n        /**\n         * The ID of the request to cancel.\n         *\n         * This MUST correspond to the ID of a request previously issued in the same direction.\n         */\n        requestId: RequestIdSchema,\n        /**\n         * An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.\n         */\n        reason: z.string().optional(),\n    }),\n});\n/* Initialization */\n/**\n * Describes the name and version of an MCP implementation.\n */\nexport const ImplementationSchema = z\n    .object({\n    name: z.string(),\n    version: z.string(),\n})\n    .passthrough();\n/**\n * Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.\n */\nexport const ClientCapabilitiesSchema = z\n    .object({\n    /**\n     * Experimental, non-standard capabilities that the client supports.\n     */\n    experimental: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the client supports sampling from an LLM.\n     */\n    sampling: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the client supports listing roots.\n     */\n    roots: z.optional(z\n        .object({\n        /**\n         * Whether the client supports issuing notifications for changes to the roots list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n})\n    .passthrough();\n/**\n * This request is sent from the client to the server when it first connects, asking it to begin initialization.\n */\nexport const InitializeRequestSchema = RequestSchema.extend({\n    method: z.literal(\"initialize\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well.\n         */\n        protocolVersion: z.string(),\n        capabilities: ClientCapabilitiesSchema,\n        clientInfo: ImplementationSchema,\n    }),\n});\nexport const isInitializeRequest = (value) => InitializeRequestSchema.safeParse(value).success;\n/**\n * Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.\n */\nexport const ServerCapabilitiesSchema = z\n    .object({\n    /**\n     * Experimental, non-standard capabilities that the server supports.\n     */\n    experimental: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the server supports sending log messages to the client.\n     */\n    logging: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the server supports sending completions to the client.\n     */\n    completions: z.optional(z.object({}).passthrough()),\n    /**\n     * Present if the server offers any prompt templates.\n     */\n    prompts: z.optional(z\n        .object({\n        /**\n         * Whether this server supports issuing notifications for changes to the prompt list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n    /**\n     * Present if the server offers any resources to read.\n     */\n    resources: z.optional(z\n        .object({\n        /**\n         * Whether this server supports clients subscribing to resource updates.\n         */\n        subscribe: z.optional(z.boolean()),\n        /**\n         * Whether this server supports issuing notifications for changes to the resource list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n    /**\n     * Present if the server offers any tools to call.\n     */\n    tools: z.optional(z\n        .object({\n        /**\n         * Whether this server supports issuing notifications for changes to the tool list.\n         */\n        listChanged: z.optional(z.boolean()),\n    })\n        .passthrough()),\n})\n    .passthrough();\n/**\n * After receiving an initialize request from the client, the server sends this response.\n */\nexport const InitializeResultSchema = ResultSchema.extend({\n    /**\n     * The version of the Model Context Protocol that the server wants to use. This may not match the version that the client requested. If the client cannot support this version, it MUST disconnect.\n     */\n    protocolVersion: z.string(),\n    capabilities: ServerCapabilitiesSchema,\n    serverInfo: ImplementationSchema,\n    /**\n     * Instructions describing how to use the server and its features.\n     *\n     * This can be used by clients to improve the LLM's understanding of available tools, resources, etc. It can be thought of like a \"hint\" to the model. For example, this information MAY be added to the system prompt.\n     */\n    instructions: z.optional(z.string()),\n});\n/**\n * This notification is sent from the client to the server after initialization has finished.\n */\nexport const InitializedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/initialized\"),\n});\nexport const isInitializedNotification = (value) => InitializedNotificationSchema.safeParse(value).success;\n/* Ping */\n/**\n * A ping, issued by either the server or the client, to check that the other party is still alive. The receiver must promptly respond, or else may be disconnected.\n */\nexport const PingRequestSchema = RequestSchema.extend({\n    method: z.literal(\"ping\"),\n});\n/* Progress notifications */\nexport const ProgressSchema = z\n    .object({\n    /**\n     * The progress thus far. This should increase every time progress is made, even if the total is unknown.\n     */\n    progress: z.number(),\n    /**\n     * Total number of items to process (or total progress required), if known.\n     */\n    total: z.optional(z.number()),\n})\n    .passthrough();\n/**\n * An out-of-band notification used to inform the receiver of a progress update for a long-running request.\n */\nexport const ProgressNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/progress\"),\n    params: BaseNotificationParamsSchema.merge(ProgressSchema).extend({\n        /**\n         * The progress token which was given in the initial request, used to associate this notification with the request that is proceeding.\n         */\n        progressToken: ProgressTokenSchema,\n    }),\n});\n/* Pagination */\nexport const PaginatedRequestSchema = RequestSchema.extend({\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * An opaque token representing the current pagination position.\n         * If provided, the server should return results starting after this cursor.\n         */\n        cursor: z.optional(CursorSchema),\n    }).optional(),\n});\nexport const PaginatedResultSchema = ResultSchema.extend({\n    /**\n     * An opaque token representing the pagination position after the last returned result.\n     * If present, there may be more results available.\n     */\n    nextCursor: z.optional(CursorSchema),\n});\n/* Resources */\n/**\n * The contents of a specific resource or sub-resource.\n */\nexport const ResourceContentsSchema = z\n    .object({\n    /**\n     * The URI of this resource.\n     */\n    uri: z.string(),\n    /**\n     * The MIME type of this resource, if known.\n     */\n    mimeType: z.optional(z.string()),\n})\n    .passthrough();\nexport const TextResourceContentsSchema = ResourceContentsSchema.extend({\n    /**\n     * The text of the item. This must only be set if the item can actually be represented as text (not binary data).\n     */\n    text: z.string(),\n});\nexport const BlobResourceContentsSchema = ResourceContentsSchema.extend({\n    /**\n     * A base64-encoded string representing the binary data of the item.\n     */\n    blob: z.string().base64(),\n});\n/**\n * A known resource that the server is capable of reading.\n */\nexport const ResourceSchema = z\n    .object({\n    /**\n     * The URI of this resource.\n     */\n    uri: z.string(),\n    /**\n     * A human-readable name for this resource.\n     *\n     * This can be used by clients to populate UI elements.\n     */\n    name: z.string(),\n    /**\n     * A description of what this resource represents.\n     *\n     * This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a \"hint\" to the model.\n     */\n    description: z.optional(z.string()),\n    /**\n     * The MIME type of this resource, if known.\n     */\n    mimeType: z.optional(z.string()),\n})\n    .passthrough();\n/**\n * A template description for resources available on the server.\n */\nexport const ResourceTemplateSchema = z\n    .object({\n    /**\n     * A URI template (according to RFC 6570) that can be used to construct resource URIs.\n     */\n    uriTemplate: z.string(),\n    /**\n     * A human-readable name for the type of resource this template refers to.\n     *\n     * This can be used by clients to populate UI elements.\n     */\n    name: z.string(),\n    /**\n     * A description of what this template is for.\n     *\n     * This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a \"hint\" to the model.\n     */\n    description: z.optional(z.string()),\n    /**\n     * The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type.\n     */\n    mimeType: z.optional(z.string()),\n})\n    .passthrough();\n/**\n * Sent from the client to request a list of resources the server has.\n */\nexport const ListResourcesRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"resources/list\"),\n});\n/**\n * The server's response to a resources/list request from the client.\n */\nexport const ListResourcesResultSchema = PaginatedResultSchema.extend({\n    resources: z.array(ResourceSchema),\n});\n/**\n * Sent from the client to request a list of resource templates the server has.\n */\nexport const ListResourceTemplatesRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"resources/templates/list\"),\n});\n/**\n * The server's response to a resources/templates/list request from the client.\n */\nexport const ListResourceTemplatesResultSchema = PaginatedResultSchema.extend({\n    resourceTemplates: z.array(ResourceTemplateSchema),\n});\n/**\n * Sent from the client to the server, to read a specific resource URI.\n */\nexport const ReadResourceRequestSchema = RequestSchema.extend({\n    method: z.literal(\"resources/read\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The URI of the resource to read. The URI can use any protocol; it is up to the server how to interpret it.\n         */\n        uri: z.string(),\n    }),\n});\n/**\n * The server's response to a resources/read request from the client.\n */\nexport const ReadResourceResultSchema = ResultSchema.extend({\n    contents: z.array(z.union([TextResourceContentsSchema, BlobResourceContentsSchema])),\n});\n/**\n * An optional notification from the server to the client, informing it that the list of resources it can read from has changed. This may be issued by servers without any previous subscription from the client.\n */\nexport const ResourceListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/resources/list_changed\"),\n});\n/**\n * Sent from the client to request resources/updated notifications from the server whenever a particular resource changes.\n */\nexport const SubscribeRequestSchema = RequestSchema.extend({\n    method: z.literal(\"resources/subscribe\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The URI of the resource to subscribe to. The URI can use any protocol; it is up to the server how to interpret it.\n         */\n        uri: z.string(),\n    }),\n});\n/**\n * Sent from the client to request cancellation of resources/updated notifications from the server. This should follow a previous resources/subscribe request.\n */\nexport const UnsubscribeRequestSchema = RequestSchema.extend({\n    method: z.literal(\"resources/unsubscribe\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The URI of the resource to unsubscribe from.\n         */\n        uri: z.string(),\n    }),\n});\n/**\n * A notification from the server to the client, informing it that a resource has changed and may need to be read again. This should only be sent if the client previously sent a resources/subscribe request.\n */\nexport const ResourceUpdatedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/resources/updated\"),\n    params: BaseNotificationParamsSchema.extend({\n        /**\n         * The URI of the resource that has been updated. This might be a sub-resource of the one that the client actually subscribed to.\n         */\n        uri: z.string(),\n    }),\n});\n/* Prompts */\n/**\n * Describes an argument that a prompt can accept.\n */\nexport const PromptArgumentSchema = z\n    .object({\n    /**\n     * The name of the argument.\n     */\n    name: z.string(),\n    /**\n     * A human-readable description of the argument.\n     */\n    description: z.optional(z.string()),\n    /**\n     * Whether this argument must be provided.\n     */\n    required: z.optional(z.boolean()),\n})\n    .passthrough();\n/**\n * A prompt or prompt template that the server offers.\n */\nexport const PromptSchema = z\n    .object({\n    /**\n     * The name of the prompt or prompt template.\n     */\n    name: z.string(),\n    /**\n     * An optional description of what this prompt provides\n     */\n    description: z.optional(z.string()),\n    /**\n     * A list of arguments to use for templating the prompt.\n     */\n    arguments: z.optional(z.array(PromptArgumentSchema)),\n})\n    .passthrough();\n/**\n * Sent from the client to request a list of prompts and prompt templates the server has.\n */\nexport const ListPromptsRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"prompts/list\"),\n});\n/**\n * The server's response to a prompts/list request from the client.\n */\nexport const ListPromptsResultSchema = PaginatedResultSchema.extend({\n    prompts: z.array(PromptSchema),\n});\n/**\n * Used by the client to get a prompt provided by the server.\n */\nexport const GetPromptRequestSchema = RequestSchema.extend({\n    method: z.literal(\"prompts/get\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The name of the prompt or prompt template.\n         */\n        name: z.string(),\n        /**\n         * Arguments to use for templating the prompt.\n         */\n        arguments: z.optional(z.record(z.string())),\n    }),\n});\n/**\n * Text provided to or from an LLM.\n */\nexport const TextContentSchema = z\n    .object({\n    type: z.literal(\"text\"),\n    /**\n     * The text content of the message.\n     */\n    text: z.string(),\n})\n    .passthrough();\n/**\n * An image provided to or from an LLM.\n */\nexport const ImageContentSchema = z\n    .object({\n    type: z.literal(\"image\"),\n    /**\n     * The base64-encoded image data.\n     */\n    data: z.string().base64(),\n    /**\n     * The MIME type of the image. Different providers may support different image types.\n     */\n    mimeType: z.string(),\n})\n    .passthrough();\n/**\n * An Audio provided to or from an LLM.\n */\nexport const AudioContentSchema = z\n    .object({\n    type: z.literal(\"audio\"),\n    /**\n     * The base64-encoded audio data.\n     */\n    data: z.string().base64(),\n    /**\n     * The MIME type of the audio. Different providers may support different audio types.\n     */\n    mimeType: z.string(),\n})\n    .passthrough();\n/**\n * The contents of a resource, embedded into a prompt or tool call result.\n */\nexport const EmbeddedResourceSchema = z\n    .object({\n    type: z.literal(\"resource\"),\n    resource: z.union([TextResourceContentsSchema, BlobResourceContentsSchema]),\n})\n    .passthrough();\n/**\n * Describes a message returned as part of a prompt.\n */\nexport const PromptMessageSchema = z\n    .object({\n    role: z.enum([\"user\", \"assistant\"]),\n    content: z.union([\n        TextContentSchema,\n        ImageContentSchema,\n        AudioContentSchema,\n        EmbeddedResourceSchema,\n    ]),\n})\n    .passthrough();\n/**\n * The server's response to a prompts/get request from the client.\n */\nexport const GetPromptResultSchema = ResultSchema.extend({\n    /**\n     * An optional description for the prompt.\n     */\n    description: z.optional(z.string()),\n    messages: z.array(PromptMessageSchema),\n});\n/**\n * An optional notification from the server to the client, informing it that the list of prompts it offers has changed. This may be issued by servers without any previous subscription from the client.\n */\nexport const PromptListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/prompts/list_changed\"),\n});\n/* Tools */\n/**\n * Additional properties describing a Tool to clients.\n *\n * NOTE: all properties in ToolAnnotations are **hints**.\n * They are not guaranteed to provide a faithful description of\n * tool behavior (including descriptive properties like `title`).\n *\n * Clients should never make tool use decisions based on ToolAnnotations\n * received from untrusted servers.\n */\nexport const ToolAnnotationsSchema = z\n    .object({\n    /**\n     * A human-readable title for the tool.\n     */\n    title: z.optional(z.string()),\n    /**\n     * If true, the tool does not modify its environment.\n     *\n     * Default: false\n     */\n    readOnlyHint: z.optional(z.boolean()),\n    /**\n     * If true, the tool may perform destructive updates to its environment.\n     * If false, the tool performs only additive updates.\n     *\n     * (This property is meaningful only when `readOnlyHint == false`)\n     *\n     * Default: true\n     */\n    destructiveHint: z.optional(z.boolean()),\n    /**\n     * If true, calling the tool repeatedly with the same arguments\n     * will have no additional effect on the its environment.\n     *\n     * (This property is meaningful only when `readOnlyHint == false`)\n     *\n     * Default: false\n     */\n    idempotentHint: z.optional(z.boolean()),\n    /**\n     * If true, this tool may interact with an \"open world\" of external\n     * entities. If false, the tool's domain of interaction is closed.\n     * For example, the world of a web search tool is open, whereas that\n     * of a memory tool is not.\n     *\n     * Default: true\n     */\n    openWorldHint: z.optional(z.boolean()),\n})\n    .passthrough();\n/**\n * Definition for a tool the client can call.\n */\nexport const ToolSchema = z\n    .object({\n    /**\n     * The name of the tool.\n     */\n    name: z.string(),\n    /**\n     * A human-readable description of the tool.\n     */\n    description: z.optional(z.string()),\n    /**\n     * A JSON Schema object defining the expected parameters for the tool.\n     */\n    inputSchema: z\n        .object({\n        type: z.literal(\"object\"),\n        properties: z.optional(z.object({}).passthrough()),\n    })\n        .passthrough(),\n    /**\n     * Optional additional tool information.\n     */\n    annotations: z.optional(ToolAnnotationsSchema),\n})\n    .passthrough();\n/**\n * Sent from the client to request a list of tools the server has.\n */\nexport const ListToolsRequestSchema = PaginatedRequestSchema.extend({\n    method: z.literal(\"tools/list\"),\n});\n/**\n * The server's response to a tools/list request from the client.\n */\nexport const ListToolsResultSchema = PaginatedResultSchema.extend({\n    tools: z.array(ToolSchema),\n});\n/**\n * The server's response to a tool call.\n */\nexport const CallToolResultSchema = ResultSchema.extend({\n    content: z.array(z.union([TextContentSchema, ImageContentSchema, AudioContentSchema, EmbeddedResourceSchema])),\n    isError: z.boolean().default(false).optional(),\n});\n/**\n * CallToolResultSchema extended with backwards compatibility to protocol version 2024-10-07.\n */\nexport const CompatibilityCallToolResultSchema = CallToolResultSchema.or(ResultSchema.extend({\n    toolResult: z.unknown(),\n}));\n/**\n * Used by the client to invoke a tool provided by the server.\n */\nexport const CallToolRequestSchema = RequestSchema.extend({\n    method: z.literal(\"tools/call\"),\n    params: BaseRequestParamsSchema.extend({\n        name: z.string(),\n        arguments: z.optional(z.record(z.unknown())),\n    }),\n});\n/**\n * An optional notification from the server to the client, informing it that the list of tools it offers has changed. This may be issued by servers without any previous subscription from the client.\n */\nexport const ToolListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/tools/list_changed\"),\n});\n/* Logging */\n/**\n * The severity of a log message.\n */\nexport const LoggingLevelSchema = z.enum([\n    \"debug\",\n    \"info\",\n    \"notice\",\n    \"warning\",\n    \"error\",\n    \"critical\",\n    \"alert\",\n    \"emergency\",\n]);\n/**\n * A request from the client to the server, to enable or adjust logging.\n */\nexport const SetLevelRequestSchema = RequestSchema.extend({\n    method: z.literal(\"logging/setLevel\"),\n    params: BaseRequestParamsSchema.extend({\n        /**\n         * The level of logging that the client wants to receive from the server. The server should send all logs at this level and higher (i.e., more severe) to the client as notifications/logging/message.\n         */\n        level: LoggingLevelSchema,\n    }),\n});\n/**\n * Notification of a log message passed from server to client. If no logging/setLevel request has been sent from the client, the server MAY decide which messages to send automatically.\n */\nexport const LoggingMessageNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/message\"),\n    params: BaseNotificationParamsSchema.extend({\n        /**\n         * The severity of this log message.\n         */\n        level: LoggingLevelSchema,\n        /**\n         * An optional name of the logger issuing this message.\n         */\n        logger: z.optional(z.string()),\n        /**\n         * The data to be logged, such as a string message or an object. Any JSON serializable type is allowed here.\n         */\n        data: z.unknown(),\n    }),\n});\n/* Sampling */\n/**\n * Hints to use for model selection.\n */\nexport const ModelHintSchema = z\n    .object({\n    /**\n     * A hint for a model name.\n     */\n    name: z.string().optional(),\n})\n    .passthrough();\n/**\n * The server's preferences for model selection, requested of the client during sampling.\n */\nexport const ModelPreferencesSchema = z\n    .object({\n    /**\n     * Optional hints to use for model selection.\n     */\n    hints: z.optional(z.array(ModelHintSchema)),\n    /**\n     * How much to prioritize cost when selecting a model.\n     */\n    costPriority: z.optional(z.number().min(0).max(1)),\n    /**\n     * How much to prioritize sampling speed (latency) when selecting a model.\n     */\n    speedPriority: z.optional(z.number().min(0).max(1)),\n    /**\n     * How much to prioritize intelligence and capabilities when selecting a model.\n     */\n    intelligencePriority: z.optional(z.number().min(0).max(1)),\n})\n    .passthrough();\n/**\n * Describes a message issued to or received from an LLM API.\n */\nexport const SamplingMessageSchema = z\n    .object({\n    role: z.enum([\"user\", \"assistant\"]),\n    content: z.union([TextContentSchema, ImageContentSchema, AudioContentSchema]),\n})\n    .passthrough();\n/**\n * A request from the server to sample an LLM via the client. The client has full discretion over which model to select. The client should also inform the user before beginning sampling, to allow them to inspect the request (human in the loop) and decide whether to approve it.\n */\nexport const CreateMessageRequestSchema = RequestSchema.extend({\n    method: z.literal(\"sampling/createMessage\"),\n    params: BaseRequestParamsSchema.extend({\n        messages: z.array(SamplingMessageSchema),\n        /**\n         * An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.\n         */\n        systemPrompt: z.optional(z.string()),\n        /**\n         * A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.\n         */\n        includeContext: z.optional(z.enum([\"none\", \"thisServer\", \"allServers\"])),\n        temperature: z.optional(z.number()),\n        /**\n         * The maximum number of tokens to sample, as requested by the server. The client MAY choose to sample fewer tokens than requested.\n         */\n        maxTokens: z.number().int(),\n        stopSequences: z.optional(z.array(z.string())),\n        /**\n         * Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.\n         */\n        metadata: z.optional(z.object({}).passthrough()),\n        /**\n         * The server's preferences for which model to select.\n         */\n        modelPreferences: z.optional(ModelPreferencesSchema),\n    }),\n});\n/**\n * The client's response to a sampling/create_message request from the server. The client should inform the user before returning the sampled message, to allow them to inspect the response (human in the loop) and decide whether to allow the server to see it.\n */\nexport const CreateMessageResultSchema = ResultSchema.extend({\n    /**\n     * The name of the model that generated the message.\n     */\n    model: z.string(),\n    /**\n     * The reason why sampling stopped.\n     */\n    stopReason: z.optional(z.enum([\"endTurn\", \"stopSequence\", \"maxTokens\"]).or(z.string())),\n    role: z.enum([\"user\", \"assistant\"]),\n    content: z.discriminatedUnion(\"type\", [\n        TextContentSchema,\n        ImageContentSchema,\n        AudioContentSchema\n    ]),\n});\n/* Autocomplete */\n/**\n * A reference to a resource or resource template definition.\n */\nexport const ResourceReferenceSchema = z\n    .object({\n    type: z.literal(\"ref/resource\"),\n    /**\n     * The URI or URI template of the resource.\n     */\n    uri: z.string(),\n})\n    .passthrough();\n/**\n * Identifies a prompt.\n */\nexport const PromptReferenceSchema = z\n    .object({\n    type: z.literal(\"ref/prompt\"),\n    /**\n     * The name of the prompt or prompt template\n     */\n    name: z.string(),\n})\n    .passthrough();\n/**\n * A request from the client to the server, to ask for completion options.\n */\nexport const CompleteRequestSchema = RequestSchema.extend({\n    method: z.literal(\"completion/complete\"),\n    params: BaseRequestParamsSchema.extend({\n        ref: z.union([PromptReferenceSchema, ResourceReferenceSchema]),\n        /**\n         * The argument's information\n         */\n        argument: z\n            .object({\n            /**\n             * The name of the argument\n             */\n            name: z.string(),\n            /**\n             * The value of the argument to use for completion matching.\n             */\n            value: z.string(),\n        })\n            .passthrough(),\n    }),\n});\n/**\n * The server's response to a completion/complete request\n */\nexport const CompleteResultSchema = ResultSchema.extend({\n    completion: z\n        .object({\n        /**\n         * An array of completion values. Must not exceed 100 items.\n         */\n        values: z.array(z.string()).max(100),\n        /**\n         * The total number of completion options available. This can exceed the number of values actually sent in the response.\n         */\n        total: z.optional(z.number().int()),\n        /**\n         * Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.\n         */\n        hasMore: z.optional(z.boolean()),\n    })\n        .passthrough(),\n});\n/* Roots */\n/**\n * Represents a root directory or file that the server can operate on.\n */\nexport const RootSchema = z\n    .object({\n    /**\n     * The URI identifying the root. This *must* start with file:// for now.\n     */\n    uri: z.string().startsWith(\"file://\"),\n    /**\n     * An optional name for the root.\n     */\n    name: z.optional(z.string()),\n})\n    .passthrough();\n/**\n * Sent from the server to request a list of root URIs from the client.\n */\nexport const ListRootsRequestSchema = RequestSchema.extend({\n    method: z.literal(\"roots/list\"),\n});\n/**\n * The client's response to a roots/list request from the server.\n */\nexport const ListRootsResultSchema = ResultSchema.extend({\n    roots: z.array(RootSchema),\n});\n/**\n * A notification from the client to the server, informing it that the list of roots has changed.\n */\nexport const RootsListChangedNotificationSchema = NotificationSchema.extend({\n    method: z.literal(\"notifications/roots/list_changed\"),\n});\n/* Client messages */\nexport const ClientRequestSchema = z.union([\n    PingRequestSchema,\n    InitializeRequestSchema,\n    CompleteRequestSchema,\n    SetLevelRequestSchema,\n    GetPromptRequestSchema,\n    ListPromptsRequestSchema,\n    ListResourcesRequestSchema,\n    ListResourceTemplatesRequestSchema,\n    ReadResourceRequestSchema,\n    SubscribeRequestSchema,\n    UnsubscribeRequestSchema,\n    CallToolRequestSchema,\n    ListToolsRequestSchema,\n]);\nexport const ClientNotificationSchema = z.union([\n    CancelledNotificationSchema,\n    ProgressNotificationSchema,\n    InitializedNotificationSchema,\n    RootsListChangedNotificationSchema,\n]);\nexport const ClientResultSchema = z.union([\n    EmptyResultSchema,\n    CreateMessageResultSchema,\n    ListRootsResultSchema,\n]);\n/* Server messages */\nexport const ServerRequestSchema = z.union([\n    PingRequestSchema,\n    CreateMessageRequestSchema,\n    ListRootsRequestSchema,\n]);\nexport const ServerNotificationSchema = z.union([\n    CancelledNotificationSchema,\n    ProgressNotificationSchema,\n    LoggingMessageNotificationSchema,\n    ResourceUpdatedNotificationSchema,\n    ResourceListChangedNotificationSchema,\n    ToolListChangedNotificationSchema,\n    PromptListChangedNotificationSchema,\n]);\nexport const ServerResultSchema = z.union([\n    EmptyResultSchema,\n    InitializeResultSchema,\n    CompleteResultSchema,\n    GetPromptResultSchema,\n    ListPromptsResultSchema,\n    ListResourcesResultSchema,\n    ListResourceTemplatesResultSchema,\n    ReadResourceResultSchema,\n    CallToolResultSchema,\n    ListToolsResultSchema,\n]);\nexport class McpError extends Error {\n    constructor(code, message, data) {\n        super(`MCP error ${code}: ${message}`);\n        this.code = code;\n        this.data = data;\n        this.name = \"McpError\";\n    }\n}\n//# sourceMappingURL=types.js.map\n```\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747179763,"content":[{"type":"text","text":"Looking at the SDK types, I see that we have access to resource notifications and updates. Let's modify our code to use the proper resource update notifications. Here's the updated version:"},{"type":"toolRequest","id":"toolu_bdrk_01J6fn7H6BderWpGjyYT1tTt","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"write","file_text":"import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools and resources to access its content.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {\n        subscribe: true, // Enable resource subscription support\n        listChanged: true // Enable resource list change notifications\n      },\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\nlet lastModified = new Date(0);\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  lastModified = new Date();\n  \n  // Send resource update notification\n  server.notify({\n    method: \"notifications/resources/updated\",\n    params: {\n      uri: \"config://goose\"\n    }\n  });\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ \n      type: \"text\", \n      text: `Last modified: ${lastModified.toISOString()}\\n\\n${currentConfig}` \n    }],\n  })\n);\n\n// Tool to check if config has changed since last check\nserver.tool(\n  \"checkConfigChanged\",\n  \"Checks if the config file has changed since a given timestamp\",\n  { \n    timestamp: z.string().describe(\"ISO timestamp to check against\") \n  },\n  { readOnlyHint: true },\n  async ({ timestamp }) => {\n    const checkTime = new Date(timestamp);\n    const hasChanged = lastModified > checkTime;\n    return {\n      content: [{ \n        type: \"text\", \n        text: hasChanged \n          ? `Config has changed. Last modified: ${lastModified.toISOString()}` \n          : \"No changes since last check\"\n      }],\n    };\n  }\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"goose_config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig,\n      mimeType: \"text/yaml\"\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  lastModified = new Date();\n  console.log('Initial config loaded');\n});\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);","path":"/Users/zane/Development/mcp_goose_configwatcher/index.ts"}}}}]}
{"role":"user","created":1747179763,"content":[{"type":"toolResponse","id":"toolu_bdrk_01J6fn7H6BderWpGjyYT1tTt","toolResult":{"status":"success","value":[{"type":"text","text":"Successfully wrote to /Users/zane/Development/mcp_goose_configwatcher/index.ts","annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/index.ts\n```typescript\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools and resources to access its content.\";\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {\n        subscribe: true, // Enable resource subscription support\n        listChanged: true // Enable resource list change notifications\n      },\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\nlet lastModified = new Date(0);\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  lastModified = new Date();\n  \n  // Send resource update notification\n  server.notify({\n    method: \"notifications/resources/updated\",\n    params: {\n      uri: \"config://goose\"\n    }\n  });\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ \n      type: \"text\", \n      text: `Last modified: ${lastModified.toISOString()}\\n\\n${currentConfig}` \n    }],\n  })\n);\n\n// Tool to check if config has changed since last check\nserver.tool(\n  \"checkConfigChanged\",\n  \"Checks if the config file has changed since a given timestamp\",\n  { \n    timestamp: z.string().describe(\"ISO timestamp to check against\") \n  },\n  { readOnlyHint: true },\n  async ({ timestamp }) => {\n    const checkTime = new Date(timestamp);\n    const hasChanged = lastModified > checkTime;\n    return {\n      content: [{ \n        type: \"text\", \n        text: hasChanged \n          ? `Config has changed. Last modified: ${lastModified.toISOString()}` \n          : \"No changes since last check\"\n      }],\n    };\n  }\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"goose_config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig,\n      mimeType: \"text/yaml\"\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  lastModified = new Date();\n  console.log('Initial config loaded');\n});\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n```\n","annotations":{"audience":["user"],"priority":0.2}}]}}]}
{"role":"assistant","created":1747179772,"content":[{"type":"text","text":"The key changes I made:\n\n1. Added proper resource capabilities:\n```typescript\ncapabilities: {\n  tools: {},\n  resources: {\n    subscribe: true, // Enable resource subscription support\n    listChanged: true // Enable resource list change notifications\n  },\n}\n```\n\n2. Added proper resource notification using the MCP protocol:\n```typescript\nserver.notify({\n  method: \"notifications/resources/updated\",\n  params: {\n    uri: \"config://goose\"\n  }\n});\n```\n\n3. Added MIME type to the resource:\n```typescript\nmimeType: \"text/yaml\"\n```\n\nNow when the config file changes:\n1. The watcher will detect the change\n2. Update the current config content\n3. Send a proper MCP resource update notification\n4. Clients can:\n   - Subscribe to config changes using `resources/subscribe`\n   - Read the current config using `resources/read`\n   - Use the tools to check for changes or get the current content\n\nLet's build and test it:"},{"type":"toolRequest","id":"toolu_bdrk_01EKKr5tDXGk2iq5gXadB5fs","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"npm run build"}}}}]}
{"role":"user","created":1747179772,"content":[{"type":"toolResponse","id":"toolu_bdrk_01EKKr5tDXGk2iq5gXadB5fs","toolResult":{"status":"success","value":[{"type":"text","text":"\n> @block/[email protected] build\n> tsc && shx chmod +x dist/*.js\n\nindex.ts(61,10): error TS2339: Property 'notify' does not exist on type 'McpServer'.\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"\n> @block/[email protected] build\n> tsc && shx chmod +x dist/*.js\n\nindex.ts(61,10): error TS2339: Property 'notify' does not exist on type 'McpServer'.\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747179794,"content":[{"type":"text","text":"I apologize for the error. It seems the `notify` method isn't directly exposed. Let's modify the code to use the transport directly:"},{"type":"toolRequest","id":"toolu_bdrk_017XLAq56mDzovu6MYoSSfgH","toolCall":{"status":"success","value":{"name":"developer__text_editor","arguments":{"command":"write","file_text":"import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools and resources to access its content.\";\n\n// Create transport first so we can use it for notifications\nconst transport = new StdioServerTransport();\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {\n        subscribe: true, // Enable resource subscription support\n        listChanged: true // Enable resource list change notifications\n      },\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\nlet lastModified = new Date(0);\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  lastModified = new Date();\n  \n  // Send resource update notification\n  transport.send({\n    jsonrpc: \"2.0\",\n    method: \"notifications/resources/updated\",\n    params: {\n      uri: \"config://goose\"\n    }\n  });\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ \n      type: \"text\", \n      text: `Last modified: ${lastModified.toISOString()}\\n\\n${currentConfig}` \n    }],\n  })\n);\n\n// Tool to check if config has changed since last check\nserver.tool(\n  \"checkConfigChanged\",\n  \"Checks if the config file has changed since a given timestamp\",\n  { \n    timestamp: z.string().describe(\"ISO timestamp to check against\") \n  },\n  { readOnlyHint: true },\n  async ({ timestamp }) => {\n    const checkTime = new Date(timestamp);\n    const hasChanged = lastModified > checkTime;\n    return {\n      content: [{ \n        type: \"text\", \n        text: hasChanged \n          ? `Config has changed. Last modified: ${lastModified.toISOString()}` \n          : \"No changes since last check\"\n      }],\n    };\n  }\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"goose_config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig,\n      mimeType: \"text/yaml\"\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  lastModified = new Date();\n  console.log('Initial config loaded');\n});\n\n// Connect server to transport\nawait server.connect(transport);","path":"/Users/zane/Development/mcp_goose_configwatcher/index.ts"}}}}]}
{"role":"user","created":1747179794,"content":[{"type":"toolResponse","id":"toolu_bdrk_017XLAq56mDzovu6MYoSSfgH","toolResult":{"status":"success","value":[{"type":"text","text":"Successfully wrote to /Users/zane/Development/mcp_goose_configwatcher/index.ts","annotations":{"audience":["assistant"]}},{"type":"text","text":"### /Users/zane/Development/mcp_goose_configwatcher/index.ts\n```typescript\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport * as chokidar from 'chokidar';\nimport * as fs from 'fs/promises';\n\nconst CONFIG_PATH = '/Users/zane/.config/goose/config.yaml';\n\n// Update the instructions for your MCP server\nconst instructions =\n  \"This MCP server watches the Goose config file for changes and provides tools and resources to access its content.\";\n\n// Create transport first so we can use it for notifications\nconst transport = new StdioServerTransport();\n\n// Create an MCP server\nconst server = new McpServer(\n  {\n    name: \"goose_config_watcher\",\n    version: \"0.0.1\",\n  },\n  {\n    capabilities: {\n      tools: {},\n      resources: {\n        subscribe: true, // Enable resource subscription support\n        listChanged: true // Enable resource list change notifications\n      },\n    },\n    instructions: instructions,\n  }\n);\n\n// Keep track of the current config content\nlet currentConfig = '';\nlet lastModified = new Date(0);\n\n// Function to read the config file\nasync function readConfig(): Promise<string> {\n  try {\n    return await fs.readFile(CONFIG_PATH, 'utf8');\n  } catch (error) {\n    console.error('Error reading config file:', error);\n    return '';\n  }\n}\n\n// Initialize the watcher\nconst watcher = chokidar.watch(CONFIG_PATH, {\n  persistent: true,\n  awaitWriteFinish: {\n    stabilityThreshold: 300,\n    pollInterval: 100\n  }\n});\n\n// Update config content when file changes\nwatcher.on('change', async (path) => {\n  console.log('Config file changed');\n  currentConfig = await readConfig();\n  lastModified = new Date();\n  \n  // Send resource update notification\n  transport.send({\n    jsonrpc: \"2.0\",\n    method: \"notifications/resources/updated\",\n    params: {\n      uri: \"config://goose\"\n    }\n  });\n});\n\n// Tool to get current config content\nserver.tool(\n  \"getConfig\",\n  \"Returns the current content of the Goose config file\",\n  {}, // no parameters needed\n  { readOnlyHint: true },\n  async () => ({\n    content: [{ \n      type: \"text\", \n      text: `Last modified: ${lastModified.toISOString()}\\n\\n${currentConfig}` \n    }],\n  })\n);\n\n// Tool to check if config has changed since last check\nserver.tool(\n  \"checkConfigChanged\",\n  \"Checks if the config file has changed since a given timestamp\",\n  { \n    timestamp: z.string().describe(\"ISO timestamp to check against\") \n  },\n  { readOnlyHint: true },\n  async ({ timestamp }) => {\n    const checkTime = new Date(timestamp);\n    const hasChanged = lastModified > checkTime;\n    return {\n      content: [{ \n        type: \"text\", \n        text: hasChanged \n          ? `Config has changed. Last modified: ${lastModified.toISOString()}` \n          : \"No changes since last check\"\n      }],\n    };\n  }\n);\n\n// Resource that provides the config content\nserver.resource(\n  \"goose_config\",\n  \"config://goose\",\n  async (uri) => ({\n    contents: [{\n      uri: uri.href,\n      text: currentConfig,\n      mimeType: \"text/yaml\"\n    }]\n  })\n);\n\n// Initialize the config content\nreadConfig().then(content => {\n  currentConfig = content;\n  lastModified = new Date();\n  console.log('Initial config loaded');\n});\n\n// Connect server to transport\nawait server.connect(transport);\n```\n","annotations":{"audience":["user"],"priority":0.2}}]}}]}
{"role":"assistant","created":1747179799,"content":[{"type":"text","text":""},{"type":"toolRequest","id":"toolu_bdrk_01QkpKeV4Vw6zutBT9gWBPv8","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"npm run build"}}}}]}
{"role":"user","created":1747179799,"content":[{"type":"toolResponse","id":"toolu_bdrk_01QkpKeV4Vw6zutBT9gWBPv8","toolResult":{"status":"success","value":[{"type":"text","text":"\n> @block/[email protected] build\n> tsc && shx chmod +x dist/*.js\n\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"\n> @block/[email protected] build\n> tsc && shx chmod +x dist/*.js\n\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747179810,"content":[{"type":"text","text":"Great! The build succeeded. Now you have a working MCP server that:\n\n1. Watches the Goose config file at `/Users/zane/.config/goose/config.yaml`\n2. Provides tools to:\n   - Get the current config content (`getConfig`)\n   - Check if config has changed since a timestamp (`checkConfigChanged`)\n3. Exposes the config as a resource at `config://goose`\n4. Sends notifications when the config changes using the MCP protocol\n\nTo use this in Goose:\n1. Enable the extension\n2. Subscribe to config changes using `resources/subscribe` with URI `config://goose`\n3. Read the config content using `resources/read` with the same URI\n4. Use the tools to check for changes or get formatted content\n\nThe LLM will receive notifications whenever the config file changes and can take appropriate actions based on those changes.\n\nWould you like me to help you test it or make any adjustments to the functionality?"}]}
{"role":"user","created":1747179838,"content":[{"type":"text","text":"Sure lets test it using the mcp inspector"}]}
{"role":"assistant","created":1747179841,"content":[{"type":"text","text":"I'll help you test the MCP server using the MCP Inspector. First, let's make sure we have the inspector and can run our server."},{"type":"toolRequest","id":"toolu_bdrk_01CUHfcVmbgoP2pTcrSRdf2r","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"npm install -g @modelcontextprotocol/inspector"}}}}]}
{"role":"user","created":1747179841,"content":[{"type":"toolResponse","id":"toolu_bdrk_01CUHfcVmbgoP2pTcrSRdf2r","toolResult":{"status":"success","value":[{"type":"text","text":"\nadded 209 packages in 19s\n\n16 packages are looking for funding\n  run `npm fund` for details\n","annotations":{"audience":["assistant"]}},{"type":"text","text":"\nadded 209 packages in 19s\n\n16 packages are looking for funding\n  run `npm fund` for details\n","annotations":{"audience":["user"],"priority":0.0}}]}}]}
{"role":"assistant","created":1747179864,"content":[{"type":"text","text":"Now let's run our MCP server in one terminal and the inspector in another. First, let's build and start our server:"},{"type":"toolRequest","id":"toolu_bdrk_01ArrXmWAsfaLmXSY5WS1bZj","toolCall":{"status":"success","value":{"name":"developer__shell","arguments":{"command":"npm run build && node dist/index.js"}}}}]}
{"role":"user","created":1747180047,"content":[{"type":"text","text":"let me run the commands"}]}
{"role":"assistant","created":1747180048,"content":[{"type":"text","text":"Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: {\"external_model_provider\":\"amazon-bedrock\",\"external_model_error\":{\"message\":\"messages.33: Did not find 1 `tool_result` block(s) at the beginning of this message. Messages following `tool_use` blocks must begin with a matching number of `tool_result` blocks.\"}}.\n\nPlease retry if you think this is a transient or recoverable error."}]}

zanesq avatar May 13 '25 23:05 zanesq

Happens to me as well, after cmd + cing running response. But it doesn't happen every time, seems random. Version 1.0.24.

{"role":"assistant","created":1748137142,"content":[{"type":"text","text":"Ran into this error: Request failed: Request failed with status: 400 Bad Request. Message: messages.191: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01MrrHpFw6AG5DUR1aHZt7Sw. Each `tool_use` block must have a corresponding `tool_result` block in the next message..\n\nPlease retry if you think this is a transient or recoverable error."}]}

fxck avatar May 25 '25 01:05 fxck

This is still happening

zanesq avatar Jun 16 '25 23:06 zanesq

This happens to me when resuming a previous session. I think it's an issue with how sessions are being stored. When I got this error I took a look at the session file, and it looks like this:

{
  "working_dir": "/home/bendavis78/Projects/my-project",
  "description": "Celery logging configuration issue",
  "message_count": 197,
  "total_tokens": 94263,
  "input_tokens": 94138,
  "output_tokens": 125,
  "accumulated_total_tokens": 4924881,
  "accumulated_input_tokens": 4906633,
  "accumulated_output_tokens": 18248
}
{
  "role": "user",
  "created": 1750449967,
  "content": [
    {
      "type": "text",
      "text": "...redacted for brevity..."
    }
  ]
}
{
  "role": "assistant",
  "created": 1750175834,
  "content": [
    {
      "type": "text",
      "text": "We can see that we're getting task registration information but not task execution logs. Let's try a more direct approach. It appears the issue might be related to the Rich logger. Let's try disabling it temporarily:"
    },
    {
      "type": "toolRequest",
      "id": "toolu_014sB4LtMysJAqfWJet9uRs8",
      "toolCall": {
        "status": "success",
        "value": {
          "name": "developer__shell",
          "arguments": {
            "command": "docker compose exec -it celery bash -c 'export PYTHONUNBUFFERED=1 && export RICH_LOGGING=False && python -m start celery'"
          }
        }
      }
    }
  ]
}
{
  "role": "user",
  "created": 1750175934,
  "content": [
    {
      "type": "toolResponse",
      "id": "toolu_014sB4LtMysJAqfWJet9uRs8",
      "toolResult": {
        "status": "error",
        "error": "Execution failed: Execution failed: Interrupted by the user to make a correction"
      }
    }
  ]
}

When I resume this session and submit any prompt, I get:

◐  Debugging reality... 
2025-06-20T20:20:53.335071Z ERROR goose::agents::agent: Error: Request failed: Request failed with status: 400 Bad Request. Message: messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_014sB4LtMysJAqfWJet9uRs8. Each `tool_use` block must have a corresponding `tool_result` block in the next message.
    at crates/goose/src/agents/agent.rs:527

You can see that the last message is has a "toolResponse" with a "toolResult". However it seems likely that goose is not properly including this when sending the conversation the LLM.

A workaround is to directly edit the file, remove the last "role": "user" message, and remove the "toolRequest" part from the last "role": "assistant" message.

bendavis78 avatar Jun 20 '25 20:06 bendavis78

this should be fixed on main now. pfew. there might still be other ways to corrupt the session though!

DOsinga avatar Aug 06 '25 11:08 DOsinga