)]}'
{
  "log": [
    {
      "commit": "4844972077e88e20243fd86f026bd10baadc70e6",
      "tree": "f01e6d497a8eecff73637cc4bbe85899134565a7",
      "parents": [
        "9d53c186ae2400c5122a3115145e55af801331ce"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 19:01:42 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 09:01:42 2026 -0700"
      },
      "message": "read one block or a list under sampling content (#685)\n\n#672 said array-valued message content wanted its own change. This is it. In the schema both `SamplingMessage.content` and `CreateMessageResult.content` take five block types or an array of them. The getter cast straight to one block, and a list on the wire threw. Both shapes now read as a list, with one block still going out as that block."
    },
    {
      "commit": "9d53c186ae2400c5122a3115145e55af801331ce",
      "tree": "ec6974dca29d0cab2ee35ed0dde7e894f2e4a582",
      "parents": [
        "6166c86f19124a9c217c6266559e98395ee9c023"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 19:01:21 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 09:01:21 2026 -0700"
      },
      "message": "answer 415 with an invalid request error (#684)\n\nIn the schema, `HeaderMismatch` carries `400 Bad Request`. This branch answers 415. A revision that requires `Mcp-Method`, `Mcp-Name` and `MCP-Protocol-Version` does not count a media type among them. Elsewhere in this file that code always pairs with 400. An oversized body already gets a generic invalid request error with its own 413, and this branch now matches it. Since this handler landed after 0.5.2, its changelog line states behaviour instead of a change."
    },
    {
      "commit": "6166c86f19124a9c217c6266559e98395ee9c023",
      "tree": "793a4304b700cc61aebd61eca5009d719a6fa540",
      "parents": [
        "47f4e3146bec18651d6a950ca041f95c0ed7d70d"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 18:18:12 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 08:18:12 2026 -0700"
      },
      "message": "add DEVELOPING.md for package:dart_mcp (#673)\n\nA short guide for working on the package. It covers where the schema files live, the checks CI runs, the SDK the format check needs, the conformance fixtures and the changelog convention. I named it DEVELOPING.md, not a second CONTRIBUTING.md, since the root already has one, and it links there. The library comment in api.dart still pointed at the 2025-06-18 schema file. It points at the schema directory now.\n\nCloses #20."
    },
    {
      "commit": "47f4e3146bec18651d6a950ca041f95c0ed7d70d",
      "tree": "6b55e6252c4fb04132e5d4533ae127f8cec9c61f",
      "parents": [
        "6c1647673bc75ded46a9bdbf500b05a9c3483169"
      ],
      "author": {
        "name": "Keerti Parthasarathy",
        "email": "keertip@users.noreply.github.com",
        "time": "Fri Sep 18 11:13:59 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 18 11:13:59 2026 -0700"
      },
      "message": "[dart_mcp_server] Publish version 1.1.2 (#683)\n\nFor publish update version string in\n - CHANGELOG.md\n - pubspec.yaml\n - lib/src/server.dart"
    },
    {
      "commit": "6c1647673bc75ded46a9bdbf500b05a9c3483169",
      "tree": "fe75d1fb6abb1efc7b078754301e21de3e68e1ea",
      "parents": [
        "7cb4308ee241e35309777eb31e5346f88789d75c"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 18 20:59:11 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 18 10:59:11 2026 -0700"
      },
      "message": "give the conformance client step a timeout (#681)\n\nThe default limit is thirty seconds per scenario. This workflow\u0027s own run stayed inside it on every non-auth scenario, and its timeouts were auth scenarios that `conformance_expected_failures.yaml` already expects. A slower machine gives a different result. Thirty-two scenarios time out on the laptop I measured on, leaving the baseline check to report unexpected failures that are not conformance gaps. Two minutes finishes with no timeouts. One minute does too. This change takes machine speed out of a weekly result.\n\nFollow-up to #675."
    },
    {
      "commit": "7cb4308ee241e35309777eb31e5346f88789d75c",
      "tree": "35d857cf1ab1de2b3a35dac7a2cb4c49f052eedf",
      "parents": [
        "53fa7718daa76f4d314c65c430d582a3bd16c972"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Sep 17 22:42:11 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Sep 17 12:42:11 2026 -0700"
      },
      "message": "add tool content types and a tools list for sampling (#672)\n\nThe 2025-11-25 revision added tool use and tool result content to sampling messages, plus a tools list on the request. Both content types now sit under `SamplingMessageContentBlock`, the union the schema gives `SamplingMessage.content`. Plain `Content` keeps the arms a `tools/call` result can carry, while text, image and audio blocks implement both unions. Retyping `SamplingMessage.content` is breaking. A tool map read through `Content.fromMap` now trips an assert, since the static types alone cannot refuse one off the wire. I left `@Deprecated` off these types, because 2026-07-28 deprecates the sampling feature and the schema keeps them. Array-valued message content wants its own change."
    },
    {
      "commit": "53fa7718daa76f4d314c65c430d582a3bd16c972",
      "tree": "a13f260c776bb7054546ac1311399669a31f1c75",
      "parents": [
        "0dc0cf64efc6c589779447ab08f5aa107d85ecdc"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 16 17:34:10 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 16 07:34:10 2026 -0700"
      },
      "message": "document input requests and mark Streamable HTTP supported (#677)\n\nRemoving elicitation, sampling and roots from the server left a readme section describing a call pattern that no longer exists. It now describes answering with an `InputRequiredResult`. That answer serves every revision. Streamable HTTP moves from :construction: to supported. Neither the handler nor the client channel carries an unfinished piece, and the row\u0027s note already names what the revision removed."
    },
    {
      "commit": "0dc0cf64efc6c589779447ab08f5aa107d85ecdc",
      "tree": "0b47828882e2ca8253faefd3d2e6ef08f433477b",
      "parents": [
        "b8c6e3e424cf0eea4a7f1a8a75c1ab0bf01414fc"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 15 23:19:20 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 15 13:19:20 2026 -0700"
      },
      "message": "follow up on the review comments on #636 (#674)"
    },
    {
      "commit": "b8c6e3e424cf0eea4a7f1a8a75c1ab0bf01414fc",
      "tree": "6f88ac67d6a40cc661807cef86914402cb401184",
      "parents": [
        "ca61d27849cd0c90ad5dfb5972b5cd9010dc6b7b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 15 22:49:16 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 15 12:49:16 2026 -0700"
      },
      "message": "run the mcp conformance suite weekly (#675)"
    },
    {
      "commit": "ca61d27849cd0c90ad5dfb5972b5cd9010dc6b7b",
      "tree": "c46f1aa454fdffdea393d389f726faf4b2d838bb",
      "parents": [
        "22944448afdd3947050c5308e026553981636b41"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 15 20:01:59 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 15 10:01:59 2026 -0700"
      },
      "message": "remove elicit, listRoots and createMessage from the server (#655)\n\nThe server request methods do not fit with how InputRequiredResult works, because handlers return input requirements as results. I removed elicit, listRoots and createMessage, a breaking API change.\n\nHandlers return an InputRequiredResult instead. On revisions before 2026-07-28 a shim wraps tools/call, prompts/get and resources/read at registration, sends each InputRequest as that revision\u0027s own request and reruns the handler with the answers, up to MCPServer.maxInputRequiredRounds rounds (8 by default). WithInputResponses gained elicitResponse, sampleResponse and listRootsResponse, and a handler reads an answer as the type it asked for.\n\nPart of dart-lang/ai#668."
    },
    {
      "commit": "22944448afdd3947050c5308e026553981636b41",
      "tree": "a806b47e507d85bf81bd8a151c62acdc1b04f462",
      "parents": [
        "4a5f1acb4d3f5d3106f774f349c4e6a4bd386dea"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 14 20:47:54 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 14 10:47:54 2026 -0700"
      },
      "message": "cancel a request when its SSE response closes (#663)\n\nAnswering a request on an SSE response means a disconnect should cancel it. This\nwatches `response.done`, then shuts the server down once the response has\nstarted. A request still on its JSON body keeps running, and a test pins that.\n\nWidening keep-alive to every SSE response also exposed the suite\u0027s `events`\nhelper. A `: keep-alive` frame carries no field lines, so `frame[\u0027data\u0027]!` threw\n`Null check operator used on a null value` whenever a handler parked past the\n50ms interval these tests use. I left comment frames out of `events` and added a\ntest that reads a stream across one."
    },
    {
      "commit": "4a5f1acb4d3f5d3106f774f349c4e6a4bd386dea",
      "tree": "147482a341d7a5e0d967de6b715b38205ee61a1c",
      "parents": [
        "b6e03bc33e3e3a5308832c1560fd38cf860cbda4"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 11 23:25:02 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 11 13:25:02 2026 -0700"
      },
      "message": "list the 2026-07-28 revision and the elicitation capability in the readme (#670)\n\nThe readme did not list 2026-07-28 under supported protocol versions, and the client capabilities table had no row for elicitation.\n\nPart of https://github.com/dart-lang/ai/issues/668"
    },
    {
      "commit": "b6e03bc33e3e3a5308832c1560fd38cf860cbda4",
      "tree": "5843f491d2de5a9cfa7c1d9edf6b83cdbba314fb",
      "parents": [
        "42ac7d9fd6ffbfc68bb7be237e4c431be561be39"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 11 23:06:49 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 11 13:06:49 2026 -0700"
      },
      "message": "add optional origin validation for Streamable HTTP (#669)\n\nAdds optional `allowedOrigins` to `handleStreamableHttpRequest`, leaving default behavior unchanged. With it set, absent or allowed origins pass, while unlisted or repeated Origin headers return an empty 403 response.\n\nI chose opt-in validation, as in TypeScript middleware and the Go handler. This is just the Origin half I said was ready in #162, and closing it is an answer if validation belongs outside the package.\n\nPart of dart-lang/ai#162"
    },
    {
      "commit": "42ac7d9fd6ffbfc68bb7be237e4c431be561be39",
      "tree": "6a5a3dd94b4064bb1beb64acb4074a10e7ddcac5",
      "parents": [
        "2f376a031bfa78b9537a84c44b47486b005aadc7"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 09 23:24:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 09 13:24:35 2026 -0700"
      },
      "message": "validate capability extension identifiers (#661)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe revision says an extension identifier has to follow the `_meta` key naming rules and carry a prefix. Nothing checked that, so a server could advertise `foo` and a client would take it.\n\nI check those keys now on every surface that writes, reads or forwards them, and the check reads without rewriting anything. The Streamable HTTP client hands each request the caller\u0027s own capabilities, so a capability set after the channel opens still arrives.\n\nAn empty name is legal under those rules, so `example/` passes, and the changelog lists the rejection under breaking."
    },
    {
      "commit": "2f376a031bfa78b9537a84c44b47486b005aadc7",
      "tree": "9c5863e542a8b0f151f239647f900b0ebb3088d9",
      "parents": [
        "e07b1727fe0beb603324dfe5ccdcff625411d4ab"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 09 23:03:41 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 09 13:03:41 2026 -0700"
      },
      "message": "add a client fixture for the conformance suite (#665)\n\nThe suite tests clients as well as servers, but `tool/` only carried the server fixture, so there was nothing to run the client leg against.\n\nThis one just branches on the scenario name the suite passes in the environment, and drives the traffic it scores. Tests run it against a server on the wire, and cover the retry when that server turns its version down. Non-auth scenarios pass 63 checks, run one at a time. The suite\u0027s parallel mode starts a client per scenario and they fall over each other here. I left `auth/*` out, since the package has no OAuth client.\n\n    npx @modelcontextprotocol/conformance@0.2.0-alpha.11 \\\n      client --command \"dart run tool/conformance_client.dart\" \\\n      --spec-version 2026-07-28 --scenario tools_call"
    },
    {
      "commit": "e07b1727fe0beb603324dfe5ccdcff625411d4ab",
      "tree": "8ebbd2cf0d6e5baa082a84c47cf11ba3d8dd30fb",
      "parents": [
        "c58d9477b8a83e3400815289c2feb82bd83c3520"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 20:45:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 10:45:07 2026 -0700"
      },
      "message": "name the transports in the package description (#666)\n\nThe pubspec report asks for 50 characters and this one is 45, so `dart_mcp` loses the pubspec points on its listing. Naming the transports carries it past the minimum without saying anything new about the package."
    },
    {
      "commit": "c58d9477b8a83e3400815289c2feb82bd83c3520",
      "tree": "b2b0ea71dc166155e3d0e5bd55681441a4b78b2b",
      "parents": [
        "42e3db2d4093ca2d454a5003812c32ecb9e162d1"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 19:23:12 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 09:23:12 2026 -0700"
      },
      "message": "pin the header walk past a matching property (#662)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe revision has a server reject a request when any mirrored header disagrees with the body. The check walks every annotated property, and nothing held it to that. On main I stopped the loop after the first property that matches its header and the suite stayed green.\n\nNothing fixes the order the properties are walked in, so the test sends both arrangements. One pairs a matching `Mcp-Param-Region` with a mismatched `Mcp-Param-Count`, the other reverses them, and both expect 400, `-32020`, and a message naming the header and the body value."
    },
    {
      "commit": "42e3db2d4093ca2d454a5003812c32ecb9e162d1",
      "tree": "2343124724808b05959169b2532251f257b65042",
      "parents": [
        "2fe3dd58c19ac755bd29104e7186787865d524de"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 19:23:06 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 09:23:06 2026 -0700"
      },
      "message": "add a padded request state to five write paths (#664)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThese tests wrote no padded request states. Trimming any of the five writes changed nothing they could see. Padded values run through all five now.\n\nThe old test name said `across JSON`, but it just decoded. I narrowed it to what the test checks."
    },
    {
      "commit": "2fe3dd58c19ac755bd29104e7186787865d524de",
      "tree": "65a4265cd29a1a8971c5e8e206b56e79f13cdd38",
      "parents": [
        "41f5a1af2e956924efb7cafe642c11ec874f8720"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 18:18:15 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 08:18:15 2026 -0700"
      },
      "message": "cap request bodies in the Streamable HTTP handler (#657)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nNothing capped a request body here. On a chunked one `contentLength` is -1, so the handler counts the bytes as they arrive. The TypeScript and Go SDKs both stop at 4 MiB with a 413, so I just did the same, as a `maxRequestBodyBytes` argument with that default. Reading past the cap stops at another `maxRequestBodyBytes`, so a body a little over still finishes and sees the response.\n\nThe error body carries `-32600`, the code this handler already uses when it refuses a batch before parsing. TypeScript answers `-32000` there."
    },
    {
      "commit": "41f5a1af2e956924efb7cafe642c11ec874f8720",
      "tree": "5d78b1b9bbbf77fe943f46b90acec9afd6c6604c",
      "parents": [
        "ce5785c044c922259142b409991c5030039f5db3"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 18:17:53 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 08:17:53 2026 -0700"
      },
      "message": "let a caller add headers to the client channel (#667)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe server handler leaves authentication to the embedding server. On the client side there was no way to send any. The channel builds its own `HttpClient`, and there was no way to hand it an `Authorization` header.\n\nIt takes a map now. The protocol\u0027s own headers are written after it, so a caller cannot replace the version, the method or a mirrored parameter."
    },
    {
      "commit": "ce5785c044c922259142b409991c5030039f5db3",
      "tree": "8e4262bb8547bf6cc571ff40a0814c6e0457592c",
      "parents": [
        "55fdf48ccf2581a68e3f54a50ddd18c51d1b50f2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 17:51:48 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 07:51:48 2026 -0700"
      },
      "message": "route server-to-client requests on older revisions (#654)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nOn revisions before 2026-07-28 the dispatcher answered a server-originated request with `-32603`, since a single-message exchange had nowhere to send it. It now takes an optional router and writes the matching response back, so the waiting peer completes.\n\nOnly those exchanges route, and the guard is explicit because a `ping` can produce a request before the version is read. Without a router I just kept the old fail-fast. A response with the wrong shape or id becomes an internal error, and one arriving after the exchange closes is dropped.\n\nThis is what the `#162` TODO in the dispatcher was waiting on."
    },
    {
      "commit": "55fdf48ccf2581a68e3f54a50ddd18c51d1b50f2",
      "tree": "e640e9047492ff14531e1e235d9c3061e1419174",
      "parents": [
        "a3fd9eb1a48079d74288a44998b372ada61f310b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 23:55:23 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 13:55:23 2026 -0700"
      },
      "message": "pin the retry and request state contracts (#658)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nTwo things the revision asks of a server held here but had no test. Nothing carried `requestState` through a round trip to show it comes back untouched, and nothing exercised a client that answers an `InputRequiredResult` without retrying.\n\nThree tests cover both now. I just left the integrity half of that paragraph alone, since this package never authorizes on the field."
    },
    {
      "commit": "a3fd9eb1a48079d74288a44998b372ada61f310b",
      "tree": "eb3c64ccb604ce4b80bec8f50810bbe6867e6886",
      "parents": [
        "93fff610865fcc080541f1c5b20b5fe9108b2cd0"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 23:03:55 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 13:03:55 2026 -0700"
      },
      "message": "answer an unsupported media type with 415 (#659)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nA POST that isn\u0027t JSON got a 400 here. The revision doesn\u0027t name a status for that, so I just followed the three SDKs that do. TypeScript answers 415 in `streamableHttp.ts:770`, Go in `mcp/streamable.go:389`, Rust in `server_side_http.rs:258`. Python stays on 400 and marks its own 415 path unreachable.\n\nThe JSON-RPC code stays `-32020`. This path calls `_reject` directly, so the status table is untouched."
    },
    {
      "commit": "93fff610865fcc080541f1c5b20b5fe9108b2cd0",
      "tree": "63624f39914c56c3f175e958f3aa9ccb2ec0ce08",
      "parents": [
        "2cccf7c07259cc7a1ee07de8a13018b96ba90c4e"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Sep 04 12:26:40 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 12:26:40 2026 -0700"
      },
      "message": "publish package:skills v1.0.1 (#660)"
    },
    {
      "commit": "2cccf7c07259cc7a1ee07de8a13018b96ba90c4e",
      "tree": "d1fb978a113a146606c710c4c44ef409f229eee5",
      "parents": [
        "ce3cfc5a1355674a3d9cb9c1b3a222f42c1e0634"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 21:40:29 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 11:40:29 2026 -0700"
      },
      "message": "accept the multi-select answers this package asks for (#656)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe two multi-select enum shapes landed in #357, and the validator from #193 turned down every array, so a client answering one of our own schemas got refused.\n\nThe check now sits on `EnumSchema` and takes a JSON array, like the rest of the package does. A `Set` would just pass here and then fail at encoding. I built the fixture from the published schema instead of the package\u0027s own builders."
    },
    {
      "commit": "ce3cfc5a1355674a3d9cb9c1b3a222f42c1e0634",
      "tree": "b4ce12a68a902286f66008246b68d4f5a293f5fa",
      "parents": [
        "ef0d8f6ae1aa47f0c41d3d1d8c4d80b76cc3248b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 19:22:50 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 09:22:50 2026 -0700"
      },
      "message": "stop telling a 2026-07-28 server the roots list changed (#652)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe 2026-07-28 revision removed `notifications/roots/list_changed`, and https://github.com/dart-lang/ai/pull/631 stopped the server sending the three input requests it removed. But `RootsSupport` just kept sending this one from the client side. I added the check inside the loop that sends it.\n\nUntil a connection settles on a revision, it still gets the notification. This does not drop the client\u0027s `roots.listChanged`."
    },
    {
      "commit": "ef0d8f6ae1aa47f0c41d3d1d8c4d80b76cc3248b",
      "tree": "d01ce6899f074985663e1fa7a7b21e1c4ca011c7",
      "parents": [
        "0fdae224e3abd1bde1678847d3bed9c9be403c93"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 19:21:47 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 09:21:47 2026 -0700"
      },
      "message": "exercise listen streams from the conformance probe (#653)\n\nWithout `SubscriptionsSupport`, the probe that #640 added answered `server/discover` with the four subscription bits stripped, and the suite skipped five server-stateless checks. I mixed it in and added the two tools that the scenario calls to change a list. The transport now gets the broadcast stream that its docs already describe.\n\nAgainst 2026-07-28 the server-stateless checks go from 25 passed with five skipped to 30 passed with none. The stream has a test in the package too, since CI does not run the suite."
    },
    {
      "commit": "0fdae224e3abd1bde1678847d3bed9c9be403c93",
      "tree": "f5d5cb61233cd3fdb90566a057cb3b9c79127188",
      "parents": [
        "7d84254f836af12369e2c5d0f67c0f028f5c5728"
      ],
      "author": {
        "name": "Nate Bosch",
        "email": "nbosch1@gmail.com",
        "time": "Thu Sep 03 19:38:34 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Sep 03 19:38:34 2026 -0700"
      },
      "message": "Use latest package:test (#626)\n\nCloses https://github.com/dart-lang/test/issues/2688\n\nThe deadlock was caused by an interaction between chrome and exe tests where the chrome process was inheriting the socket server bound to communicate with the exe test.\n\nWorkaround landed in https://github.com/dart-lang/test/pull/2740"
    },
    {
      "commit": "7d84254f836af12369e2c5d0f67c0f028f5c5728",
      "tree": "cdda2bb4f571ace4fff230180e28a4ea2b6c2c84",
      "parents": [
        "f03fe1a1e3935fceccc323575ab325ef54df13e2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 22:30:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 12:30:35 2026 -0700"
      },
      "message": "serve the subscriptions/listen notification stream (#636)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe `subscriptions/listen` types landed without a handler. I put the acknowledgement contract on the mixin instead of the Streamable HTTP dispatcher, since the spec states it for every transport. It stamps the subscription id on the first message, holds the request until shutdown, and refuses a listen the transport did not name. Matching list and resource notifications go onto the open response, and closing it just ends the subscription without a final result.\n\nAn embedder can feed a shared notification stream so a change from one request reaches another listen. Public factories, the subscription-id shape, and the `discover` advertisement change with this wire."
    },
    {
      "commit": "f03fe1a1e3935fceccc323575ab325ef54df13e2",
      "tree": "e9f6f109d42d96f51f5e19e55410417208c2d1f3",
      "parents": [
        "c4de9ff82b3f833a0ea13fe6bf6784d55e8cf120"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 22:30:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 12:30:07 2026 -0700"
      },
      "message": "cache client responses from server hints (#635)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe client reuses complete results for the six 2026-07-28 operations that\ncarry caching hints, keyed by the parameters and the request metadata. I\nwrapped `sendRequestKeepingProgress` so `sendRequestWithInputs` still hits\nthe cache. Entries drop on change notifications, a stale cursor, and\n`shutdown`. The cache belongs to one `ServerConnection`. A `private` result\nnever leaves the authorization context it came from.\n\nThe multi round-trip page never mentions caching. The caching utilities page\n(https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching)\nsays an `input_required` result is not cacheable, and a retry carrying\n`inputResponses` or `requestState` MUST NOT be cached. I kept both out even\nwhen a `resources/read` payload also sends the hints."
    },
    {
      "commit": "c4de9ff82b3f833a0ea13fe6bf6784d55e8cf120",
      "tree": "ef2f979127e3ad2477a814396b0a5b1757ae0c28",
      "parents": [
        "e85bf1c9bee8b650deece8276647a6ffca2c6a5d"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 19:24:19 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 09:24:19 2026 -0700"
      },
      "message": "add a local mcp conformance probe (#640)\n\nCloses https://github.com/dart-lang/ai/issues/491\n\n#572 shipped Streamable HTTP. The blocker named in that issue is gone. I added a local HTTP probe under tool/ as development tooling, not package API.\n\ncrypto is a dev_dependency used only to HMAC opaque requestState. The suite runs from Node, and the integration guide offers a reusable Action instead of requiring one. I left the bots alone.\n\nAgainst `@modelcontextprotocol/conformance@0.2.0-alpha.11`, `--requirements 2026-07-28` is 37/37 and `--suite all --spec-version 2026-07-28` is 40/40. Thirteen more scenarios run without scoring, ten of them the tasks extension this package does not implement. The other three are pending and pass."
    },
    {
      "commit": "e85bf1c9bee8b650deece8276647a6ffca2c6a5d",
      "tree": "eb31466f1fa8364e950632fdc5980b12cf584608",
      "parents": [
        "035eca55321ccae020b5b49309d7861d49c0680a"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 19:23:52 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 09:23:52 2026 -0700"
      },
      "message": "make schema iterables JSON encodable (#644)\n\nSets and lazy iterables in seven schema fields made `jsonEncode` fail. This follows up on [the issue I noted in #603](https://github.com/dart-lang/ai/pull/603#discussion_r3792311104) now that it has landed.\n\nWith no matching package precedent, I think the constructor is the natural boundary for converting each value to a fixed-length list. A compact table test covers all seven fields through `jsonEncode`."
    },
    {
      "commit": "035eca55321ccae020b5b49309d7861d49c0680a",
      "tree": "6c89fc1143c39d44f254509b3258dc93b216870e",
      "parents": [
        "135dd698e35748fce55e71bb9f11bede4eee9d2b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 19:12:36 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 09:12:36 2026 -0700"
      },
      "message": "let the create tool target the project root (#642)\n\nThe create tool rejected a `directory` of `.`. The check leans on `p.isWithin`,\nand that is strict enough to call `isWithin(\u0027.\u0027, \u0027.\u0027)` false, reading it as an\nescape from the project root.\n\nI let the root through for Flutter, where `flutter create .` works. A Dart\nproject still needs a subdirectory, because the Dart CLI wants an empty target\nunless it is forced, and forcing is not something this tool does. The error says\nthat now. An empty string lands in the same place as `.`, and it is rejected on\nits own."
    },
    {
      "commit": "135dd698e35748fce55e71bb9f11bede4eee9d2b",
      "tree": "2e3b68cf6a4d1b5df679517e7775e208fffece6d",
      "parents": [
        "db510a3a9d3cbb748c315fa442f62eca9f4996f6"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Tue Sep 01 08:53:28 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 08:53:28 2026 -0700"
      },
      "message": "Bump the github-actions group with 4 updates (#645)\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "db510a3a9d3cbb748c315fa442f62eca9f4996f6",
      "tree": "46f78cfbf6de54b7b2f47eda842f4bb898d86e11",
      "parents": [
        "91107a55f74d834c913baa5e6e8ad4fff1f5541e"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 01:07:29 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 15:07:29 2026 -0700"
      },
      "message": "let tool, prompt and resource handlers answer with an input-required result (#637)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nhttps://github.com/dart-lang/ai/pull/622 left the handler return types alone. A server still cannot answer `tools/call`, `prompts/get` or `resources/read` with an `InputRequiredResult`. This widens the three of them to `CallToolResponse`, `GetPromptResponse` and `ReadResourceResponse`, which the completed result and `InputRequiredResult` both implement.\n\nRust names the same three. I kept the supertypes constructorless so `_fromMap` stays private. Extension types cannot be told apart by `is`, so `Result.isInputRequired` reads the result type instead.\n\nIt is a breaking change, and the handler parameters widen with it. Callers on 2025-11-25 see no difference, because what they already return satisfies the wider type. The `dart_mcp_server` package resolves the published 0.5.x, so its six sites move when 0.6.0 lands."
    },
    {
      "commit": "91107a55f74d834c913baa5e6e8ad4fff1f5541e",
      "tree": "467d43958fb0d1d02118cb258a5df44c387fad24",
      "parents": [
        "db457476e44ccceba0983a711242a92683ba876f"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 00:03:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 14:03:07 2026 -0700"
      },
      "message": "add a Streamable HTTP client channel (#638)\n\nStreamable HTTP still lacked a client channel. I put `streamableHttpClientChannel` next to the server handler so the header names stay one definition.\n\nFailures come back on the id that asked for them. A notification has none, so it only hears about a POST that already went out.\n\nThe helper requires a protocol version up front, since it never sends `initialize`. The Tools page requires Streamable HTTP clients to exclude invalid `tools/list` entries (https://modelcontextprotocol.io/specification/2026-07-28/server/tools#x-mcp-header)."
    },
    {
      "commit": "db457476e44ccceba0983a711242a92683ba876f",
      "tree": "14cc83e0b87cff054a488340689b3aee9b45813c",
      "parents": [
        "a106f3f568878652277021fac96358584d1c5368"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 31 20:01:08 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 10:01:08 2026 -0700"
      },
      "message": "wait before a retry that carries no input requests (#639)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nNothing paced the leg the TODO named, so the client could retry the moment the server answered. `ServerConnection.inputRequiredRetryDelay` now holds it off for 250 ms, and `null` disables that. An empty map waits too, since it asks for nothing. Where the server does hand back work, resolving it already costs time, so those rounds are untouched.\n\nThe number comes from `packages/core-internal/src/shared/inputRequiredDriver.ts` in the TypeScript SDK, which sleeps a flat 250 ms there. Python caps a backoff at the same figure. I took the flat wait, since a constant pause on each of these rounds keeps the loop off the wire."
    },
    {
      "commit": "a106f3f568878652277021fac96358584d1c5368",
      "tree": "e14307556804b7b7885f280b9a67fa1935407f44",
      "parents": [
        "e630be7f2a2c86b66f8da34c14c1c12ec869057b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 31 20:00:45 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 10:00:45 2026 -0700"
      },
      "message": "reject real whitespace in a create template (#643)\n\nThe create tool accepted a template carrying a newline or a tab. The check\nlooked for a literal backslash-n. Only a space was caught, and the message\nalready promised more than that.\n\nI just swapped both string checks for one whitespace pattern. The message now\nmatches what the code does. A template carrying a literal backslash-n gets\nthrough now, and one carrying a non-breaking space does not."
    },
    {
      "commit": "e630be7f2a2c86b66f8da34c14c1c12ec869057b",
      "tree": "f33930ba587605e8ba27ffd7aea5086c42f4c4be",
      "parents": [
        "ba495eebdb133e35ac59669a5cc6b9f3adab9b07"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Aug 28 14:26:17 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 14:26:17 2026 -0700"
      },
      "message": "pin ecosystem workflow actions to hashes (#634)"
    },
    {
      "commit": "ba495eebdb133e35ac59669a5cc6b9f3adab9b07",
      "tree": "6abd41bdb0c9ac8ff81105ce72ec84f6b891f12c",
      "parents": [
        "7c01a0d32e10147285d54d06693125d55ab14c0e"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 23:37:52 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 13:37:52 2026 -0700"
      },
      "message": "answer the input requests in an input_required result (#632)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe client half of MRTR. On an `input_required` result the connection fills in\nwhat the server asked for and sends the call again. A request it cannot build\nfails the call instead of answering the rest.\n\nThe handshake stops at 2025-11-25, so only a transport setting the version\nitself reaches 2026-07-28. I made `protocolVersion` nullable. Nothing fills in\n`serverInfo` there either, and both sampling paths name it.\n\n`ServerConnection` gains `sendRequestWithInputs` for a mixin adding an\nextension method. `maxInputRequiredRounds` moves the cap off ten. `MCPBase`\ngains `@protected` `sendRequestKeepingProgress` and `closeProgress`. A retry\nholds one progress token across its rounds."
    },
    {
      "commit": "7c01a0d32e10147285d54d06693125d55ab14c0e",
      "tree": "ecfce6f58ca2fbb1a7f25b416c6475a1fb92b4f2",
      "parents": [
        "6dd5be9af2777ce16ad9a24b1d7c51985ffbb9d3"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 23:00:54 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 13:00:54 2026 -0700"
      },
      "message": "validate x-mcp-header params in the Streamable HTTP handler (#627)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe server never read the `Mcp-Param-*` headers this revision defines. A header that contradicted the body was ignored. The spec asks for a 400 and -32020 there.\n\nValidating one needs the tool\u0027s input schema, so I put a `beforeDispatch` hook on the request-scoped entry point and the transport hands it the initialized server. Reading a schema from there needed `ToolsSupport.registeredTools`, a read-only view. I did not want to run someone\u0027s `listTools` override on every call.\n\nOn #580 you preferred an error, or an assert if it had to be masked. Here the invalid thing is the tool definition, not the server: the 2026-07-28 page says clients \"MUST reject tool definitions where any `x-mcp-header` value violates these constraints\". An out-of-spec annotation goes unread instead."
    },
    {
      "commit": "6dd5be9af2777ce16ad9a24b1d7c51985ffbb9d3",
      "tree": "9b6a639cc9fdf7e725bb48c26b8de9fca5088f02",
      "parents": [
        "edb9c1c04b5b0ed7e0eaae5c020d04532eea8375"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:58:27 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:58:27 2026 -0700"
      },
      "message": "decode SSE response bodies on the client (#629)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe client side has no SSE reader yet, so I added `sseMessageStream`. A frame that fails to decode arrives as an error while the stream keeps reading, since one bad frame probably should not cost the whole response. A truncated frame never arrives and bad bytes become the replacement character. The HTML specification asks for both.\n\nThe decoder sits under `src/utils` because it needs nothing from `dart:io`. The `events` helper in the transport tests reads a whole string. It stays for now. I want this for the client transport, the next slice."
    },
    {
      "commit": "edb9c1c04b5b0ed7e0eaae5c020d04532eea8375",
      "tree": "b3d958d0b245ecf5823c6872e7dfe8fceb5cbc79",
      "parents": [
        "9f4196b59b8b49c266b25bb227bb708cc9075540"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:50:10 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:50:10 2026 -0700"
      },
      "message": "Set client serverInfo only when version negotiation succeeds (#633)\n\n`ServerConnection.serverInfo` already documented that it is only non-null once\n`initialize` succeeds, but `initialize` assigned it before looking at the\nversion. A connection shut down over an unsupported version still held the\nrejected server\u0027s implementation.\n\nI moved the assignment next to `protocolVersion`, so it just lands in the\nbranch that runs when the version is one we support. `ServerConnection.name`\nreads through it. A rejected connection now logs as `unknown`."
    },
    {
      "commit": "9f4196b59b8b49c266b25bb227bb708cc9075540",
      "tree": "8561976fd5d36b8ce1d2174fbdfc22520563344f",
      "parents": [
        "9e1e64fa916989b0c23078ceb87cd386c83ed4c1"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:49:53 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:49:53 2026 -0700"
      },
      "message": "add the client side of server/discover (#630)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe package answers `server/discover`, but a client sending one had to build\nthe request itself. On this revision the whole request is reserved `_meta`\nkeys.\n\nI added `ServerConnection.discover`. It takes the two required keys as\narguments instead of a `DiscoverRequest`, so a probe cannot go out without\nthem, while `MCPServer.discover` still takes one. Client info, a log level and\na progress token go in when they are given. The result just comes back as it\narrived. A probe leaves the connection\u0027s own state alone.\n\nThe envelope keys get their own type, `MetaWithRequestEnvelope`, extending\n`MetaWithProgressToken`."
    },
    {
      "commit": "9e1e64fa916989b0c23078ceb87cd386c83ed4c1",
      "tree": "dc006b70e8d690724751383aebaf64452c9e1a48",
      "parents": [
        "d320d70fbc8e6e582746bb536b6696c1b6b0d488"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:49:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:49:35 2026 -0700"
      },
      "message": "reject server-to-client requests the revision does not have (#631)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nOn 2026-07-28 a server could still send the three requests that ask a client\nfor input. That revision keeps their types for the `InputRequiredResult` that\ncarries them, but drops the `ServerRequest` union they went out through, and\n`removedMethods` never picked that up.\n\nI listed them there and had the senders read that check first. It also refuses\n`elicit` on the two revisions that predate `elicitation/create`.\n\nThe other senders still go out unchecked, `resources/subscribe`,\n`resources/unsubscribe`, `logging/setLevel` and `ping` among them."
    },
    {
      "commit": "d320d70fbc8e6e582746bb536b6696c1b6b0d488",
      "tree": "62135b1ca832edcb86b28e4f0c0f02c68c0dd213",
      "parents": [
        "6248d08f0267b15e22bd369e4222078612aadb28"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 21:28:48 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 11:28:48 2026 -0700"
      },
      "message": "refuse input_required results a client cannot act on (#628)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe dispatcher passed an `input_required` result straight through. A server could answer tools/list that way, or ask for an elicitation the client never declared. 2026-07-28 allows neither.\n\nAnswering that way on a method outside prompts/get, resources/read and tools/call is now an internal error, as is a malformed input request. I send an undeclared capability through `_missingClientCapability`, just the -32021 a live connection raises. I pulled those refusals out for the dispatcher and the server methods to share. Tool use is the one check that goes further, needing `sampling.tools` where `createMessage` looks only for `sampling`."
    },
    {
      "commit": "6248d08f0267b15e22bd369e4222078612aadb28",
      "tree": "53d74dd09a62daad9e576316a069719589ea145b",
      "parents": [
        "8240e23a02eb4f9b8d5a9c6937305432526e5974"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Aug 27 15:21:13 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 15:21:13 2026 -0700"
      },
      "message": "Bump the github-actions group across 1 directory with 3 updates (#625)\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "8240e23a02eb4f9b8d5a9c6937305432526e5974",
      "tree": "bc11358d6b9090e8d09047f35cfa0a7a9b0ced16",
      "parents": [
        "879efce376183bcf10a55f89da0fd46f1d5711fd"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 27 14:24:10 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 14:24:10 2026 -0700"
      },
      "message": "Add missing license headers (#624)\n\nAdds missing license/copyright headers to files flagged during open source review.\n\n- Add BSD-style copyright headers across repository config, workflows, `dart_mcp`, `dart_mcp_server`, and `counter_app` test fixture files.\n- Update `CHANGELOG.md` for `dart_mcp` and `dart_mcp_server`."
    },
    {
      "commit": "879efce376183bcf10a55f89da0fd46f1d5711fd",
      "tree": "c34c1e944a5d2bdea202f3afc94aee6f4d898683",
      "parents": [
        "5c336fad18dae8ff761d003000b530500ffa2d8b"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 27 14:21:15 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 14:21:15 2026 -0700"
      },
      "message": "Clean up skills CLI tests (#623)\n\nThis PR fixes tests breaking in non-TTY environments due to ANSI output injection by explicitly wrapping tests evaluating multi-select dialogs in `overrideAnsiOutput(false, ...)`. Additionally, changes `GitSync` raw `stderr.writeln` to use `package:logging` so that clone warnings are correctly swallowed by test suites.\n\nIt also fixes one test that was running the CLI in the current working directory instead of the temp directory, which was leaving artifacts on disk."
    },
    {
      "commit": "5c336fad18dae8ff761d003000b530500ffa2d8b",
      "tree": "fde96443f081d2bb3d0a354ca7b56747919a98bf",
      "parents": [
        "37ede8afc1790006c883baa434be0c0575e0df29"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 27 08:02:53 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 08:02:53 2026 -0700"
      },
      "message": "Ignore uninstalled and missing skills in skills list (#617)\n\nFixes #607\n\n- Filter out skills with `isInstalled: false` in `ListCommand`\n- Filter out skills that no longer exist on disk in `ListCommand`\n- Filter out empty packages and agents with no installed skills in `ListCommand`\n- Filter out `isInstalled: false` in `SkillManifest.allSkills` and `allSkillsForAgent`\n- Add changelog entry for package:skills\n- Add regression tests in `list_command_test.dart` and `skill_manifest_test.dart`"
    },
    {
      "commit": "37ede8afc1790006c883baa434be0c0575e0df29",
      "tree": "ea3d9cdcb304c613c4ec0b1f57c74c8645985160",
      "parents": [
        "1bf21ac740ff045aa63e54f5575cac52bd39aa43"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 27 17:59:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 07:59:35 2026 -0700"
      },
      "message": "add input-response request fields (#622)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThis adds the request side of https://github.com/dart-lang/ai/pull/602. The three requests a server can answer with an `InputRequiredResult` now take an `inputResponses` map and a `requestState`, which is what a retry carries back.\n\nI left the handler return types alone for now. Nothing sends or reads these yet, and widening those three signatures would be a breaking change."
    },
    {
      "commit": "1bf21ac740ff045aa63e54f5575cac52bd39aa43",
      "tree": "c32e608607915f3225307e01b557ef4c4146b691",
      "parents": [
        "fa55c819d66c70f9ebde2af27a421f4415d391a2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 27 00:48:02 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 26 14:48:02 2026 -0700"
      },
      "message": "finish a changelog merge that kept both sides (#621)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nA merge in #610 hit a conflict in the unreleased notes and kept both sides. The sentence saying the server does not answer `server/discover` yet came back from before its removal in #596, and that PR\u0027s replacement ending landed seven lines lower with nothing above it.\n\nI kept the #596 side."
    },
    {
      "commit": "fa55c819d66c70f9ebde2af27a421f4415d391a2",
      "tree": "1ec58c2cd635790c8e6c7ab787ffaf2f7860f4f6",
      "parents": [
        "17ecdc963fc30ac473e84f6206793a8e1e9bf2df"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Aug 25 14:23:02 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 25 14:23:02 2026 -0700"
      },
      "message": "add a package:skills issue template (#619)"
    },
    {
      "commit": "17ecdc963fc30ac473e84f6206793a8e1e9bf2df",
      "tree": "cea2355a72b3eb24faecb9ce60e7d5392441a5b3",
      "parents": [
        "94aca951c5ad779847e6ec28b77afc36428c4ce6"
      ],
      "author": {
        "name": "Eric Windmill",
        "email": "ewindmill@google.com",
        "time": "Mon Aug 24 10:01:46 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 24 10:01:46 2026 -0700"
      },
      "message": "Add detail to instructions for creating a skill (#615)\n\nI\u0027m 0th customer-ing package:skills. This PR adds a bit more detail to the skill template and clarifies some documentation."
    },
    {
      "commit": "94aca951c5ad779847e6ec28b77afc36428c4ce6",
      "tree": "bf83455c823abf04fd27122b3a0b8c8fb3506c0d",
      "parents": [
        "33fcb6610db74aa6589fa41f113127d212528d42"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 24 17:55:28 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 24 07:55:28 2026 -0700"
      },
      "message": "check the elicitation mode at both ends (#614)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe server side only asked whether the client had `elicitation`, but a client declares which modes it takes and the [spec](https://modelcontextprotocol.io/specification/2026-07-28/client/elicitation#capabilities) says a server must not send one it did not. A url-only client saw form requests and declined them as if the user had.\n\nI split that guard into `supportsFormElicitation` and `supportsUrlElicitation`, and both ends now answer an unknown mode with invalid params. Auto-handling a `-32042` only runs when the request inside it names url. Both are breaking. The resolved getter throws on an unknown one, so the guards read a new `rawMode`."
    },
    {
      "commit": "33fcb6610db74aa6589fa41f113127d212528d42",
      "tree": "9a36da85d25e60b63795dbe3fae981e40662fb25",
      "parents": [
        "bfbcab2fe39f22453027d4d37021d10430c310f3"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 22 00:23:34 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:23:34 2026 -0700"
      },
      "message": "answer a notifying request on an SSE response stream (#610)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nNotifications a handler emits while it works now reach the caller on an SSE response stream instead of being dropped. The first one commits the response to `text/event-stream`, so a call that never notifies keeps its JSON body. Progress and log messages ride their own request\u0027s stream. The four list-changed and resource-updated notifications stay off it, since a `subscriptions/listen` request owns those.\n\nThe README row and the dartdoc that named response streams as missing now describe this. A client closing the stream is not treated as cancellation yet, which the specification requires once a server streams."
    },
    {
      "commit": "bfbcab2fe39f22453027d4d37021d10430c310f3",
      "tree": "7318939f85b0106d0470bc01d0fce71cbf029b4d",
      "parents": [
        "1e2cc7a6fe049f3adc62b443d19bf7c7162a432d"
      ],
      "author": {
        "name": "Keerti Parthasarathy",
        "email": "keertip@users.noreply.github.com",
        "time": "Fri Aug 21 14:19:16 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:19:16 2026 -0700"
      },
      "message": "[dart_mcp_server] Add a field to capture the agent plugin information in analytics (#612)\n\nThis PR \n- pulls in unified_analytics v 8.0.17\n- reads the plugin info from env\n- adds the plugin information to the MCP analytics events\n- added test to verify the changes"
    },
    {
      "commit": "1e2cc7a6fe049f3adc62b443d19bf7c7162a432d",
      "tree": "829690f6ec7836d98d1a30de597c401d42b62fcf",
      "parents": [
        "977a139b7cb6ae7549c593937c71ab5b3f0933be"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 22 00:09:06 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:09:06 2026 -0700"
      },
      "message": "fix the thisService spelling and the number field casts (#613)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe `IncludeContext` enum has spelled one value `thisService` since 0.1.0. No schema revision spells it that way, and the factory puts the enum name straight on the wire. I kept the old name as a deprecated alias, the same way `ElicitationAction` keeps `reject`. A client on 0.5.2 or earlier throws on the corrected name.\n\nFive getters cast the schema\u0027s number fields to a `double`. A whole number arriving from a peer throws except on the JavaScript platforms. They read `num` now. The `temperature` parameter only took an integer, which ruled out the `0.1` the spec\u0027s own `sampling/createMessage` request sends."
    },
    {
      "commit": "977a139b7cb6ae7549c593937c71ab5b3f0933be",
      "tree": "eb46255b324a455a795a860acead277719036591",
      "parents": [
        "7471b6e6778a721273c401a289419f9271764607"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 22 00:05:00 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:05:00 2026 -0700"
      },
      "message": "update the spec links to modelcontextprotocol.io and 2025-11-25 (#611)\n\nThe package has 42 spec links and 28 of them do not load. They sit in the readme and five source files. Most point at spec.modelcontextprotocol.io, which no longer serves HTTPS. Most also use revision 2025-11-05, never published. The same typo got fixed in `ProtocolVersion` in https://github.com/dart-lang/ai/pull/366, and that change moved the changelog link onto the canonical host too, so I followed it here. I kept 2025-11-25, since that is what `latestSupported` still points to."
    },
    {
      "commit": "7471b6e6778a721273c401a289419f9271764607",
      "tree": "aa39fdfee106e7560b02c93cef3a7a641a473546",
      "parents": [
        "9c1356d85c8939c666e41f1965013df776f30e4c"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:50:09 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:50:09 2026 -0700"
      },
      "message": "serve server/discover from MCPServer (#596)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe discover types landed without a dispatcher, so `server/discover` answered -32601 on a revision that requires it. I put the handler on the server, registered only from 2026-07-28 on, since answering is itself the claim to that lifecycle and the [stdio probe](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio#backward-compatibility) keys on it. TypeScript and Python gate it to the same revision.\n\nCapabilities are a public final field now and `initialize` no longer returns them. That is breaking. Mixins edit the object in place. The capabilities constructor was also skipping `completions`, just a missing line, fixed here."
    },
    {
      "commit": "9c1356d85c8939c666e41f1965013df776f30e4c",
      "tree": "3266f16abed97a57e48262ab6b0e0ee7e3eccd26",
      "parents": [
        "d81cf26a9ba025afe3f42fb85bb28462778f7e50"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:45:28 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:45:28 2026 -0700"
      },
      "message": "fix four schema types in tools.dart against the spec (#603)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nFour of the schema types in `tools.dart` disagree with the JSON Schema the spec points at.\n\nInteger bounds were typed as ints. JSON Schema types them as numbers, and the spec gives integers and numbers one definition. A valid `minimum: 0.5` threw on read. Number, integer and boolean schemas could not carry a default at all, leaving a server able to pre-fill a text field but not a checkbox. Two equal maps decoded from JSON got past `uniqueItems` on a list schema, since it compared them with `Set`. I picked up the enum factories spelling their own keys while I was in there."
    },
    {
      "commit": "d81cf26a9ba025afe3f42fb85bb28462778f7e50",
      "tree": "577cdae6648965b6de8d667bf564fc60ed732a48",
      "parents": [
        "5e3bfa2697fb40a0e6271ca645b3fdcaf488120b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:21:19 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:21:19 2026 -0700"
      },
      "message": "compare the wire error codes against the numbers (#599)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe wire tests read the error code back off the response body and compare it to the constant the server built it from, so renumbering moves both sides together. I wrote the numbers out on the expected side in the three tests that cover the codes #571 added, and did the same in the elicitation retry test, where the number is what the client recognizes."
    },
    {
      "commit": "5e3bfa2697fb40a0e6271ca645b3fdcaf488120b",
      "tree": "61dd929e72d963fb52011d761002cc7ad7735c64",
      "parents": [
        "ccdf18870ddde7a91a3b0ff3bb60df4a3b8b1f6b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:07:43 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:07:43 2026 -0700"
      },
      "message": "update the Meta dartdoc to the reverse DNS prefix rule (#605)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThese docs still describe the 2025-06-18 prefix rule, where a prefix was reserved if `modelcontextprotocol` or `mcp` sat in any label but the last. The 2025-11-25 revision keys it off the second label instead, so two of the four examples we carry, `modelcontextprotocol.io/` and `mcp.dev/`, are not reserved any more. The `io.modelcontextprotocol/` prefix we write keys under only became reserved with that change. I added the OpenTelemetry exception from 2026-07-28, since these docs do not mention it."
    },
    {
      "commit": "ccdf18870ddde7a91a3b0ff3bb60df4a3b8b1f6b",
      "tree": "251179255879bef01628a82d0a3ced61a33e43a0",
      "parents": [
        "e0f09442cd28b5a00edfbc3ecc0b0d2082b68364"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:07:27 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:07:27 2026 -0700"
      },
      "message": "add the input-required result types (#602)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nOn 2026-07-28 a server answers `tools/call`, `prompts/get` or `resources/read` with an `input_required` result when it needs something from the client first. The result carries the requests it needs under server-assigned keys, and a `requestState` the client sends back untouched on the retry. This adds those two types. Nothing dispatches them yet."
    },
    {
      "commit": "e0f09442cd28b5a00edfbc3ecc0b0d2082b68364",
      "tree": "1e3f722262acab09c3c5055488b8a1ebb8c45e81",
      "parents": [
        "18a3e34902d3315ab76e506b86b46c76a5eb2946"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:02:06 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:02:06 2026 -0700"
      },
      "message": "stop two optional resource fields from throwing (#600)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe size getter on `Resource` is declared `int?` but cast to a non-nullable `int`. Any resource that just left the field out threw. Its twin on `ResourceLink` already reads that same optional field nullably.\n\nIcons on a resource link were typed as a list of strings while the schema has typed them as icons since the field was added. Reading them off a link a server sent threw on the first element. The getter type changing is what breaks. I matched the five other types which carry icons, factory included."
    },
    {
      "commit": "18a3e34902d3315ab76e506b86b46c76a5eb2946",
      "tree": "61e037e56672cc9d7b9ea58c308f7675a163728c",
      "parents": [
        "e0f707336544d445b2deb8282e4bffeffd46b9da"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 22:54:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 12:54:07 2026 -0700"
      },
      "message": "omit optional fields instead of writing them as null (#601)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nFive factories write an explicit `null` when an optional field is not given, and the schema does not allow null there. No other SDK puts those keys on the wire: python drops none values on the way out, go and rust leave an unset optional off it."
    },
    {
      "commit": "e0f707336544d445b2deb8282e4bffeffd46b9da",
      "tree": "05f06e535e514ec791a7413de248b272067def4b",
      "parents": [
        "f7d7ba6504d05c8a75cc13e4dc5303ebce7747d4"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 14 00:36:15 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 14:36:15 2026 -0700"
      },
      "message": "send notifications/message only when a 2026-07-28 request asks (#595)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nOn 2026-07-28 the log level travels in each request\u0027s `_meta`, as [`io.modelcontextprotocol/logLevel`](https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/logging). A server must send no `notifications/message` for a request that omits the key, and `LoggingSupport` was still sending them at its warning default.\n\nI put the level on `MCPServerInitialization`, filled by the streamable HTTP handler from the envelope key beside the reserved ones it already reads. An unrecognized value comes back as `-32602`. That leaves the warning default just for 2025-11-25 and older, where `logging/setLevel` still sets it."
    },
    {
      "commit": "f7d7ba6504d05c8a75cc13e4dc5303ebce7747d4",
      "tree": "23f78df060725271f7fa74377fc7e2c7e773572d",
      "parents": [
        "6142d5f0e199a6b84b9872cff4b19ba0f020acce"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 13 10:06:06 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 10:06:06 2026 -0700"
      },
      "message": "publish package:skills 1.0.0 (#598)"
    },
    {
      "commit": "6142d5f0e199a6b84b9872cff4b19ba0f020acce",
      "tree": "bbfdbe094ec076ae38081d15099891c6f2516e64",
      "parents": [
        "b9e0c539e9609718c1773cab539e01113ecfbaa2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 13 17:45:58 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 07:45:58 2026 -0700"
      },
      "message": "reject the methods the 2026-07-28 revision removed (#593)\n\nThe gate in `handleStreamableHttpRequest` only covered the two legacy lifecycle methods, but the [2026-07-28 revision](https://modelcontextprotocol.io/specification/2026-07-28/changelog) removed more than those. Every server answered `ping` with `200`, since it comes from `MCPBase`. A server picks up `logging/setLevel` and the two `resources` subscription methods from the mixins, and `notifications/roots/list_changed` from the roots capability.\n\n`ProtocolVersion` now carries what each revision added and removed. The transport asks it, so a handler registered later gets the same `404`.\n\nPart of #162."
    },
    {
      "commit": "b9e0c539e9609718c1773cab539e01113ecfbaa2",
      "tree": "5b40b241c18e1e8f24e881398b3e4f1e3df84996",
      "parents": [
        "625d43ffa1e56f5700e031c7b2fba6a690b59627"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 13 17:33:56 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 07:33:56 2026 -0700"
      },
      "message": "add a test that the list endpoints keep their registration order (#594)\n\nThe 2026-07-28 spec asks servers to return tools from `tools/list` in a deterministic order. `tools/list`, `prompts/list` and `resources/list` already do, since those registries are map literals and `.values` iterates in insertion order. Nothing pinned the order though: on main, reversing all three results breaks no test.\n\nThe new test lists tools, prompts and resources twice each and expects registration order back, which is stricter than the SHOULD but is the order the package produces today. I picked names that are neither ascending nor descending, so a sort in either direction fails.\n\nPart of #162."
    },
    {
      "commit": "625d43ffa1e56f5700e031c7b2fba6a690b59627",
      "tree": "da2b0ce568963bec4fdb178c6c0e0a5ed8eda58d",
      "parents": [
        "5342cf3ec0bfe363f3c0e17277cfcfcc2925a400"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 13 17:32:17 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 07:32:17 2026 -0700"
      },
      "message": "refuse listRoots and createMessage without the client capability (#597)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nBoth `listRoots` and `createMessage` sent their request no matter what the client\ndeclared, so an undeclared capability just surfaced as whatever the peer happened\nto answer, and on a request-scoped transport that is a generic internal error.\nThe 2026-07-28 revision requires -32021 naming the capability under\n`data.requiredCapabilities`, the same error `elicit` already returns.\n\nI hoisted `supportsRoots` onto the base class where those two methods live and\nadded `supportsSampling` beside it, since dart_mcp_server already computes both\nby hand for its analytics. This is breaking for a server which expects the codes\nthe peer used to produce."
    },
    {
      "commit": "5342cf3ec0bfe363f3c0e17277cfcfcc2925a400",
      "tree": "a23857079c6c5ecd2028c9491f9496a639ccd9eb",
      "parents": [
        "15cec357fbb123d3ab3553e8b327d688a22a1be9"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Aug 11 19:28:50 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 11 09:28:50 2026 -0700"
      },
      "message": "add the capability extensions maps from protocol 2026-07-28 (#592)\n\nAdds the `extensions` map the [2026-07-28 revision](https://modelcontextprotocol.io/specification/2026-07-28/changelog) puts on both capability objects.\n\nThe same revision moves the whole `tasks` surface out of the core schema and into `io.modelcontextprotocol/tasks`, which the schema uses as its example key for the server map. Each extension defines its own settings object, so values stay an opaque `Map\u003cString, Object?\u003e` like `experimental`.\n\nPart of #162."
    },
    {
      "commit": "15cec357fbb123d3ab3553e8b327d688a22a1be9",
      "tree": "aeb8c003b372ab7ad2cdf219884e5f658c50f0ac",
      "parents": [
        "7c80f1bb32fb4d3a336f9b181f1dff36d4086873"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 10 23:01:41 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 13:01:41 2026 -0700"
      },
      "message": "add the subscriptions/listen types from protocol 2026-07-28 (#589)\n\nThe 2026-07-28 revision replaces the HTTP GET endpoint, `resources/subscribe`, and `resources/unsubscribe` with a single stream opened by `subscriptions/listen`. `SubscriptionFilter.resourceSubscriptions` carries the URIs the two removed requests took, and `SubscribeRequest` and `UnsubscribeRequest` stay for the revisions that have them. The server acknowledges on `notifications/subscriptions/acknowledged` with the types it agreed to send, and the id travels in `_meta` under `io.modelcontextprotocol/subscriptionId`.\n\nNothing dispatches the method yet. Its response is an SSE stream, which `streamable_http.dart` does not implement.\n\nPart of #162."
    },
    {
      "commit": "7c80f1bb32fb4d3a336f9b181f1dff36d4086873",
      "tree": "fbbf36171919aa6efe1db831a4448b20207f18bf",
      "parents": [
        "3d06d93008ff9567ae56f460a715f4e697e930d6"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 10 23:01:28 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 13:01:28 2026 -0700"
      },
      "message": "report -32602 when a resource URI has no handler (#587)\n\n`readResource` threw an `ArgumentError` for a URI with no resource or template, which reached the client as `-32000` with a Dart stack trace. The [2026-07-28 revision](https://modelcontextprotocol.io/specification/2026-07-28/server/resources#error-handling) asks for `-32602` carrying the URI as `data.uri`, so it throws `RpcException` now. This breaks servers which override `readResource` and catch that `ArgumentError`.\n\n`json_rpc_2` adds the request to `data`, so the frame carries `{uri, request}`, and the TypeScript SDK only rebuilds its `ResourceNotFoundError` from an exact `{uri}`.\n\nPart of #162."
    },
    {
      "commit": "3d06d93008ff9567ae56f460a715f4e697e930d6",
      "tree": "63a4d97b6972d08c0a882e7b5f87043ed06754f4",
      "parents": [
        "dde2f6d34025ce324b7d4c8aebb2cfd6a7d0bf22"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 10 22:04:59 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 12:04:59 2026 -0700"
      },
      "message": "emit -32021 when a client asks to elicit without the capability (#588)\n\nNext 2026-07-28 core-protocol slice tracked in #162, following #571 and #572: `ElicitationRequestSupport.elicit` now produces `-32021` when the client did not declare the elicitation capability.\n\n#571 added `missingRequiredClientCapability` and #572 mapped it to `400`, but nothing in the library produces it. The one throw site is `test/needsSampling`, a tool registered to exercise that mapping.\n\n`callTool` already sorts these apart: an `RpcException` is rethrown and reaches the client as an RPC error, while anything else becomes a `CallToolResult` with `isError: true` whose text is the exception and stack trace. `elicit` was throwing a `StateError`, on the wrong side of that split. A tool which elicits against such a client came back indistinguishable from one which crashed, carrying nothing machine-readable about what was missing.\n\nIt now throws an `RpcException` carrying `data.requiredCapabilities`, both of which the schema marks required on this error. The payload names the top-level `elicitation` capability, matching the gate that failed: `supportsElicitation` is a null check on `clientCapabilities.elicitation` and does not separate the `form` and `url` modes the way the TypeScript SDK does. Narrowing it belongs with that gate.\n\nBreaking for a server catching the `StateError`, though nothing here does: `grep_packages` checks the capability itself and returns early, and neither call site in the example catches by type. `RpcException` comes from `package:json_rpc_2`, already a direct dependency that `example/elicitations_server.dart` imports and throws today.\n\n## Tests\n\n- That case now comes back as `-32021`, with the capability under `data.requiredCapabilities`. The mapping from that code to `400` is already covered.\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (1122 tests across the four configurations, the new one in all of them).\n- `dart analyze --fatal-infos` is clean here and in `mcp_examples` resolved against this branch.\n\nPart of #162."
    },
    {
      "commit": "dde2f6d34025ce324b7d4c8aebb2cfd6a7d0bf22",
      "tree": "4ce0b632357d4f7915e9f7734624da6819ed04f1",
      "parents": [
        "b319a464d5a4ddfe79d9d7f45d989ad2c12e10c7"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 10 21:23:46 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 11:23:46 2026 -0700"
      },
      "message": "add the server/discover types from protocol 2026-07-28 (#584)\n\nNext 2026-07-28 core-protocol slice tracked in #162, following #570 and #579: the types for `server/discover`, the unlanded core support named in the [finalized-spec diff report](https://github.com/dart-lang/ai/issues/162#issuecomment-5108248966).\n\nServers on this revision must implement the method, and the package already points at it: `example/README.md` says a client that calls it gets `-32601` back, and the dartdoc on `handleRequestScopedMessage` tells readers that clients in this lifecycle \"discover capabilities with `server/discover` rather than per message\". Both stay true, since this adds the types without wiring the method into the dispatcher.\n\n- `DiscoverRequest` carries nothing of its own: the schema gives it only the `_meta` envelope, and `handleStreamableHttpRequest` rejects a request that arrives without one.\n- Until now the factory tests skipped `server/discover`, \"which this package does not serve yet\" and which had no type to construct in any case. `DiscoverResult` implements `CacheableResult` and its factory takes `ttlMs` and `cacheScope` on the same terms as the five factories from #579, so that carve-out comes off and the group iterates all six.\n- `supportedVersions` is a `List\u003cString\u003e`, not a `List\u003cProtocolVersion\u003e`, because that enum is a closed set and `tryParse` answers null for anything it cannot name.\n- `serverInfo` is not a field on the result. The finalized revision moved it into the reserved `io.modelcontextprotocol/serverInfo` metadata key. `handleRequestScopedMessage` fills that key in when a handler leaves it out.\n\n## Tests\n\n- The request\u0027s map is empty until it is given metadata, and the result writes the fields it is given and leaves out the ones it is not; those are asserted on the map, as in #579. A decoded map reads back through the getters, and the closed-enum case is pinned directly: `2027-11-05` fails `ProtocolVersion.tryParse` and still comes through `supportedVersions`.\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (1118 tests across the four configurations, the six new ones in all of them).\n- `dart analyze --fatal-infos` is clean here and in `mcp_examples` resolved against this branch.\n\nPart of #162."
    },
    {
      "commit": "b319a464d5a4ddfe79d9d7f45d989ad2c12e10c7",
      "tree": "1c449a9fa882d2cc011a5a67fa4e96878ad62804",
      "parents": [
        "4a6359b134c4f9f44511d7680daf0fde77df6625"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Aug 07 11:29:16 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 07 11:29:16 2026 -0700"
      },
      "message": "publish dart_mcp_server version 1.1.1 (#583)\n\nThis includes some additional instructions and better errors for hot reload related tasks."
    },
    {
      "commit": "4a6359b134c4f9f44511d7680daf0fde77df6625",
      "tree": "0321dbd776ed552ffcb33e3b06eca63946c0a23b",
      "parents": [
        "fca1cda3de799c3bbc624e964c286ed8766405c7"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 07 18:33:01 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 07 08:33:01 2026 -0700"
      },
      "message": "send the result fields the 2026-07-28 revision requires (#580)\n\nNext 2026-07-28 core-protocol slice tracked in #162, following #565 and #570: the request-scoped dispatcher now sends `resultType`, `ttlMs`, and `cacheScope`. #579 is the other half, how a handler supplies the two hints itself.\n\nBoth landed read-only, and both closed with a note that server-side emission was a later slice.\n\n- Every result on 2026-07-28 carries a `resultType`. The schema types the field as required for a server on this revision (https://modelcontextprotocol.io/specification/2026-07-28/schema#result-resulttype), and the dispatcher was leaving it off, so every result the Streamable HTTP handler returned was missing it.\n- The list and read results also carry the caching hints those rules require (https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching). `resources/read` is the one of them the schema also answers with an interim result (https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr), so it is the only one whose result type excuses the hints.\n- All of it is gated on the negotiated revision, including the reserved `_meta` key from #528: it is 2026-07-28 vocabulary too. `handleRequestScopedMessage` takes the version in its `MCPServerInitialization` and is exported for transports this package does not own, so it cannot assume the revision the way `handleStreamableHttpRequest` can.\n- A field the handler set is kept when the schema allows it; an assert catches one it does not, and the dartdoc on `handleRequestScopedMessage` lists what replaces it in a build with asserts disabled.\n\nThis sits in the server info stamping from #528 rather than in the result factories, because the fields belong to a protocol revision and the same server also serves 2025-11-25 over stdio.\n\n`\u0027complete\u0027` moved to `ResultTypes` in `constants.dart`, so the value the reader folds to and the value the dispatcher writes are one definition.\n\n## Tests\n\n- A result type is recorded, and one the handler chose is kept. The hints are recorded on `tools/list` and on `resources/read`, and not on `tools/call`. Hints the handler chose are kept, one hint given and one left out is completed, and fields left `null` are replaced. An interim `resources/read` gets no hints while an interim-typed `tools/list` still gets them. An earlier revision gets none of it. All asserted on the result map, since no existing test pins the set of keys on a result. A value the schema rejects fails an assert instead.\n- The dispatch tests now negotiate 2026-07-28, since the request-scoped lifecycle arrived with it; the earlier revision has its own test.\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (1094 tests across the four configurations).\n- `dart analyze --fatal-infos` is clean here and in `mcp_examples` resolved against this branch.\n\nPart of #162."
    },
    {
      "commit": "fca1cda3de799c3bbc624e964c286ed8766405c7",
      "tree": "0876593172a1848b827febdb5d5548e041a26d8f",
      "parents": [
        "d8a9d7939244c5de63312ad899bc756beedfd680"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 06 12:38:04 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 12:38:04 2026 -0700"
      },
      "message": "Update README to include version badges (#582)\n\nAdded version badges for dart_mcp_server and skills packages."
    },
    {
      "commit": "d8a9d7939244c5de63312ad899bc756beedfd680",
      "tree": "c1bfd53ad79d2c8a33d271e75aa74e13c96efb21",
      "parents": [
        "83ad94635271c885fc951a015c0d2092f595cb33"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Aug 05 20:29:21 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 05 10:29:21 2026 -0700"
      },
      "message": "fix RequestId so it can hold a JSON-RPC id (#581)\n\n`RequestId` is an extension type over `json_rpc_2`\u0027s `Parameter`, while its\nsibling `ProgressToken` uses `Object` for the same `String|int` union. Reading\n`CancelledNotification.requestId` therefore throws for every id a peer can\nsend, and no id can be constructed to pass to the factory:\n\n```\ntype \u0027int\u0027 is not a subtype of type \u0027Parameter?\u0027 in type cast\npackage:dart_mcp/src/api/api.dart 235:54  CancelledNotification.requestId\n```\n\nNothing reads or builds `CancelledNotification` in this package, which is why\nthis went unnoticed. Changing the representation to `Object` drops the last\n`json_rpc_2` import from `api.dart`.\n\n## Tests\n\n- A `CancelledNotification` round-trips an `int` id and a `String` id.\n- `dart test` passes (294 tests)."
    },
    {
      "commit": "83ad94635271c885fc951a015c0d2092f595cb33",
      "tree": "28e71f5698e9f1f8187e747e2123b18995ef4d34",
      "parents": [
        "5cb0ae17703f57e2097d4656ce3e7efb30209809"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Aug 05 17:09:01 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 05 07:09:01 2026 -0700"
      },
      "message": "let servers set the caching hints on cacheable results (#579)\n\nNext 2026-07-28 core-protocol slice tracked in #162, following #570: the five cacheable result factories now take the `ttlMs` and `cacheScope` caching hints. #580 is the other half, what the dispatcher fills in when a handler did not.\n\n#570 added `CacheableResult` to read the two off a result and closed with \"server-side emission of the hints (factory parameters) are follow-up slices\". This is that slice, for the results the caching rules name (https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching).\n\n- Both are optional and are left out of the result when they are not passed. Writing a default `ttlMs` here would be indistinguishable from a real answer, since an absent one and a written `0` both read as `0`. Writing a default `cacheScope` would be worse: synthesizing `public` for a server that never declared a scope is the one guess that can leak a private response into a shared cache, which is why #570 has the getter read `null` instead.\n- A negative `ttlMs` is an assertion failure. The spec requires `ttlMs \u003e\u003d 0`, and the reader already folds a negative value to `0`, so a server sending one would be telling clients something other than what it meant. Same shape as `Annotations`\u0027 assert on `priority`.\n- `ReadResourceResult` takes the two without `nextCursor`, matching the schema: it is cacheable but not paginated.\n- They are two parameters rather than one hints object because the factory is where these fields are defined, so a third hint would land here anyway, and because every other factory in the package takes its fields this way.\n\nThat page also names `server/discover`, which this package does not serve yet, so five factories change here.\n\n## Tests\n\n- Each factory writes both hints when given them, writes just the one it is given, and leaves both keys out when given neither. The assertions read the result map rather than the getters, since an absent `ttlMs` and a written `ttlMs: 0` both read as `0`. That `0` is covered explicitly: it is a meaningful value in the spec, not a sentinel.\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (1040 tests across the four configurations).\n- `dart analyze --fatal-infos` is clean here and in `mcp_examples` resolved against this branch.\n\nOne note on what is not tested: the `ttlMs` assert has no test. Asserts are compiled out under `-c exe`, so a test which expects one to throw fails there, and the package tests none of its 37 other asserts either.\n\nPart of #162."
    },
    {
      "commit": "5cb0ae17703f57e2097d4656ce3e7efb30209809",
      "tree": "7d3a82079e05009877f2e416fc2d83392880cc27",
      "parents": [
        "e6192ee4c85254417b66fbc034712f62b32bf950"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Aug 04 07:08:47 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 04 07:08:47 2026 -0700"
      },
      "message": "Improve hot reload flow with more proactive instructions and better errors (#578)\n\nPart of https://github.com/dart-lang/ai/issues/498\n\n- When agents do read the server instructions (which they may not do up front),  this helps them more pro-actively use hot reload and connect to apps.\n- When agents try to use a tool incorrectly because they forgot to read the schema, the error message now tells them to read the schema and try again. AGY seems to try and invoke tools without reading their schema semi-regularly.\n  - I updated this in the core dart_mcp package as well as our own package. We do our own validation in a slightly different way, so we have some of this code duplicated."
    },
    {
      "commit": "e6192ee4c85254417b66fbc034712f62b32bf950",
      "tree": "28b379edb4647349bd134a6b259f5fbf6a1b6023",
      "parents": [
        "88f2bb6a8d2bc85e1f5c9ac2acbbf5feeae11ae4"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 03 22:59:17 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 12:59:17 2026 -0700"
      },
      "message": "add the streamable HTTP POST handler from protocol 2026-07-28 (#572)\n\nNext 2026-07-28 slice tracked in #162, the POST handler laid out in the [finalized-spec diff report](https://github.com/dart-lang/ai/issues/162#issuecomment-5108248966). Rebased onto main now that #571 has landed, so nothing here predates that.\n\nAdds `package:dart_mcp/streamable_http.dart` with `handleStreamableHttpRequest`, the server side of the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http) from the finalized revision. Each POST carries one JSON-RPC request or notification which is validated against the required headers and `_meta` envelope, then dispatched to a fresh server instance via `handleRequestScopedMessage`. Responses are JSON only. Also adds `ProtocolVersion.v2026_07_28`; `ProtocolVersion.latestSupported` still points at 2025-11-25, the newest version the legacy `initialize` handshake negotiates, since a transport for the request-scoped protocol carries its own set of supported versions.\n\nTwo mapping decisions worth calling out:\n\n- Accept and Content-Type failures are answered with 400 Bad Request rather than 406/415: the 2026-07-28 schema requires 400 on every `HeaderMismatch` body (\"For HTTP, the response status code MUST be `400 Bad Request`\"), and the revision names no other status for content negotiation.\n- A notification POST is acknowledged with 202 before the header checks run; the spec\u0027s note on notification POSTs states \"header requirements for notification POSTs are not defined by this revision\".\n\n`example/streamable_http_server.dart` serves one tool over the transport and prints a `curl` command for it.\n\nDoes not add SSE response streams, the legacy session routes, or an HTTP client; those land as separate slices in that order.\n\n## Tests\n\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes: 1028 tests (293 in each VM configuration, 221 in each Chrome configuration; the new suite is `@TestOn(\u0027vm\u0027)` since it drives `dart:io` sockets).\n- `dart analyze --fatal-infos`: no issues.\n- `cd mcp_examples \u0026\u0026 dart pub get \u0026\u0026 dart analyze --fatal-infos`: no issues."
    },
    {
      "commit": "88f2bb6a8d2bc85e1f5c9ac2acbbf5feeae11ae4",
      "tree": "3c3782dbaa62e24dc5959d67cb8704672a32483c",
      "parents": [
        "bca0afc48e99f810c1c4342e2e8fc05c5aaef5b6"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 01 00:44:33 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 31 14:44:33 2026 -0700"
      },
      "message": "Report the install directory in skills get output (#573)\n\nFixes #552.\n\nAfter installing, the per-agent summary named the agent but not where the\nskills actually went. It now names the directory:\n\nBefore:\n\n    Installed 2 skill(s) for generic.\n    Installed 2 skill(s) for claude.\n\nAfter:\n\n    Installed 2 skill(s) for generic at .agents/skills.\n    Installed 2 skill(s) for claude at .claude/skills.\n\nThis follows the display you added to `skills list` in #554 (d1405de), whose\nheader is `claude (installed at .claude/skills):` — same project-relative\ndirectory, same `at` preposition. The value here is `agent.skillsRelativePath`\nrather than `p.split(p.relative(adapter.skillsDirectory, from: rootPath)).join(\u0027/\u0027)`;\nI checked all six adapters on multiple roots and the two produce identical\nstrings, so this avoids pulling `package:path` into `get_skills.dart` while\nstaying consistent with what `list` prints.\n\nNot included: a location on each per-skill line. The directory is constant per\nagent, so repeating it on every skill is noise, and `InstalledSkillInfo`\ncarries no path — threading one through `_installSkills` →\n`_PackageInstallResult` → `SkillInstallResult` would multiply the diff for that\nnoise. Happy to do it if you disagree.\n\nThis touches `get_skills.dart` and the `## 1.0.0-wip` CHANGELOG, the same two\nfiles as your open #568. I merged the two locally and they apply cleanly, so\nthere\u0027s nothing to coordinate.\n\nTest covers two agents with different directories in a single `get` run."
    },
    {
      "commit": "bca0afc48e99f810c1c4342e2e8fc05c5aaef5b6",
      "tree": "1abb244a85bca49a870e7915d6002d0d5fa049f2",
      "parents": [
        "ee17018cde13bf1ec0c042a2a1a5b83e81b0b642"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Jul 31 14:26:21 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 31 14:26:21 2026 -0700"
      },
      "message": "increase test timeout for flaky tests (#576)\n\nThis test has been flaking a bunch on the latest flutter beta, it appears that `flutter pub get` is slower than it used to be."
    },
    {
      "commit": "ee17018cde13bf1ec0c042a2a1a5b83e81b0b642",
      "tree": "5aa7b7a297a1310f7728b771d9e07f6bf7a03233",
      "parents": [
        "c65be8f83eee14036e28c772e83cdb479ee44341"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Jul 31 14:24:05 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 31 14:24:05 2026 -0700"
      },
      "message": "feat(skills): clean up unused git repo sources in skills prune and skills get (#568)\n\nResolves #562\n\n### Summary of Changes\n\n- **Prune Utility (`lib/src/core/pruner.dart`)**:\n  - Extracted package dependency skill pruning and git repository source cleanup into a reusable `pruneSkills` function.\n  - Checks both local (`skills_config.json`) and global (`global_config.json`) configurations for git repo sources with 0 installed skills.\n  - Presents candidate unreferenced package dependencies and empty local git repo sources to the user in a unified multi-select dialog (`showMultiSelectDialog`).\n  - Presents candidate empty global git repo sources in a multi-select dialog.\n  - Early-bails if dialog support is unavailable and `--all` flag is false.\n  - Supports `--all` (`allFlag: true`) to skip prompts and automatically prune all candidate packages and empty git sources.\n\n- **Commands**:\n  - **`skills prune`**: Updated `PruneCommand` to support `-a`/`--all` flag and delegate to `pruneSkills`.\n  - **`skills get`**: Invokes `pruneSkills` with `quietIfNothingToPrune: true` at the completion of `getSkills` so unused skills and zero-skill git sources are cleaned up automatically after getting skills.\n\n- **Tests \u0026 Docs**:\n  - Added unit tests for package and local/global git repo pruning in `test/commands/prune_command_test.dart` using declarative `test_descriptor` `.validate()` assertions.\n  - Updated `README.md` to document the new `prune` source cleanup behavior and highlight `--git \u003crepo\u003e` options.\n  - Updated `CHANGELOG.md`."
    },
    {
      "commit": "c65be8f83eee14036e28c772e83cdb479ee44341",
      "tree": "05507d944c6b3bb39090adf3b2c88d9dcfb17b0a",
      "parents": [
        "307a8a1702ee0b675c990c1fc7e9eb55fd002873"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Jul 30 19:41:31 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 30 09:41:31 2026 -0700"
      },
      "message": "add the error code constants from protocol 2026-07-28 (#571)\n\nNext 2026-07-28 slice tracked in #162, split out ahead of the HTTP transport work as laid out in the [finalized-spec diff report](https://github.com/dart-lang/ai/issues/162#issuecomment-5108248966).\n\nAdds the three error-code constants the finalized revision renumbered into the range it reserves for the specification, see the new [error-code registry](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2026-07-28/basic/index.mdx):\n\n- `headerMismatch` (`-32020`), for a Streamable HTTP request whose required headers are missing or do not match the body. The RC carried this as `-32001` in transport prose only; the final schema types it as `HeaderMismatchError`.\n- `missingRequiredClientCapability` (`-32021`) and `unsupportedProtocolVersion` (`-32022`), renumbered from the RC\u0027s `-32003`/`-32004` into the reserved `-32020..-32099` range.\n- `urlElicitationRequired`\u0027s doc now records that the registry reserves `-32042` and only the 2025-11-25 revision emits it.\n\nNothing emits these yet; the POST handler slice picks them up next.\n\n## Tests\n\n- Constants only, no behavior change; `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (220 tests in each of the four configurations)."
    },
    {
      "commit": "307a8a1702ee0b675c990c1fc7e9eb55fd002873",
      "tree": "b433412f8a3372f3f93f932e95795f6f8ddc4aab",
      "parents": [
        "ca364abfdcda60626afd112bccf0169f23403de3"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Mon Jul 27 15:22:24 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 15:22:24 2026 -0700"
      },
      "message": "Emphasize the actual skill name in dialogs (#549)\n\nBolds actual skill names in CLI selection dialog options, separating them from package or framework prefixes.\n\nFixes #548"
    },
    {
      "commit": "ca364abfdcda60626afd112bccf0169f23403de3",
      "tree": "5baa6a64ced765c2fbc07f6d40ea4a9866d1271d",
      "parents": [
        "d1405defdc9182b068ad53fb6d07c0a9de0755c2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Jul 28 01:12:32 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 15:12:32 2026 -0700"
      },
      "message": "add CacheableResult from protocol 2026-07-28 (#570)\n\nNext 2026-07-28 core-protocol slice tracked in #162, following #565 and kept separate from the HTTP transport work.\n\nAdds the `CacheableResult` \"mixin\" extension type and the `CacheScope` enum, modeling the caching hints from https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2549:\n\n- `CacheableResult.ttlMs` reads the TTL hint as an `int`. The spec requires servers to send `ttlMs \u003e\u003d 0` and tells clients to treat both an absent value and a negative one as `0` (https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/server/utilities/caching.mdx; servers on earlier protocol versions never send the field), so the getter reads `0` for both. Same fold `Result.resultType` does with `complete`.\n- `CacheableResult.cacheScope` reads the scope as a nullable `CacheScope`. The schema types the field as a closed `\"public\" | \"private\"` union with no absent-value default, so the getter is an enum like the package\u0027s other closed unions (`Role`, `LoggingLevel`) but resolves the way `Schema.type` does: an absent or unrecognized value reads as `null` instead of throwing, which keeps results from older servers readable and leaves room for the still-draft schema to grow the union before the RC.\n- The type mirrors `PaginatedResult`: no public constructor, \"mixed in\" by other extension types. The schema attaches it to the four list results, `ReadResourceResult`, and the new `DiscoverResult`; the five that already exist in this package now implement it, so the hints are readable on the results the client API already returns. `DiscoverResult` itself and server-side emission of the hints (factory parameters) are follow-up slices.\n\n## Tests\n\n- `ttlMs` reads `0` on an empty result and for a negative value, `cacheScope` reads `null` when absent, both parse when present, an unrecognized scope string reads as `null`, and a `ListToolsResult` carrying the fields exposes both.\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (220 tests in each of the four configurations).\n- `dart analyze --fatal-infos` is clean here and in `mcp_examples` resolved against this branch.\n\nPart of #162."
    },
    {
      "commit": "d1405defdc9182b068ad53fb6d07c0a9de0755c2",
      "tree": "9d488efce392775af1671ad1aa5fce61f6af3b57",
      "parents": [
        "816e82c74e537af164e09f2c33f9a6e92c5706c0"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Mon Jul 27 15:03:09 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 15:03:09 2026 -0700"
      },
      "message": "Make list command more consistent and informative (#554)\n\nFixes #550.\n\n- Agent labels now include aliases in parentheses (e.g. `generic (antigravity, codex)`).\n- Displays the actual install directory for each agent in the section header (e.g. `(installed at .agents/skills)`).\n- Appends a note at the end indicating these are only managed skills and additional skills may be installed.\n- Stores the relative repository path of skills in the manifest and displays it in `skills list` output (e.g. `- skill-name (repo path: path/to/skill)`)."
    },
    {
      "commit": "816e82c74e537af164e09f2c33f9a6e92c5706c0",
      "tree": "315070d62f12b7a61f2143d7406e431fdd6c509e",
      "parents": [
        "eb11f5958f226e538d29d67a1d14cc1af896564c"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Jul 24 12:28:58 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 12:28:58 2026 -0700"
      },
      "message": "Auto-select suggested skill repos in source-selection dialog (#558) (#569)\n\nWhen installing suggested skill repos in `skills get`, exclude them from the subsequent source-selection prompt since the user already accepted them.\n\nFixes #558"
    },
    {
      "commit": "eb11f5958f226e538d29d67a1d14cc1af896564c",
      "tree": "cf8e078f49366806f206f5a32ec1020df18e2030",
      "parents": [
        "4cde5c9df356fc8f68cac8b80186f2ba380f0fcd"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Jul 24 20:24:00 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 10:24:00 2026 -0700"
      },
      "message": "add Result.resultType from protocol 2026-07-28 (#565)\n\nFirst slice of the 2026-07-28 core-protocol support tracked in #162, split out from the HTTP transport work to keep it small and reviewable on its own.\n\nAdds the `resultType` result field as an additive, non-breaking API:\n\n- `Result.resultType` reads the field. A null value means the server did not send it; callers treat null as `complete`, the backward-compatible convention the 2026-07-28 schema requires for results from servers on earlier protocol versions. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2726, which reframes an absent `resultType` as backward compatibility.\n- The getter is a nullable `String`, exactly matching `CreateMessageResult.stopReason` (both `String?`), the open union this package already has. The schema types `resultType` as `\"complete\" | \"input_required\" | string`, so a server may send a value this package does not know. A closed `enum` cannot represent that set; it would have to throw on an unknown value or fold it into a fallback constant, and both lose the string the server actually sent. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2773, the SEP-2322 fix that made `ResultType` an open union so servers can extend it.\n- No `latestSupported` bump and no server-side emission; those are later slices. This is the read side, so a client parses `resultType` from a 2026-07-28 server correctly without waiting for the rest.\n\n## Tests\n\n- `resultType` is null when the field is absent, and passes both a known value and an unknown string through unchanged.\n- `dart test -p chrome,vm -c dart2wasm,dart2js,kernel,exe` passes (219 tests in each of the four configurations).\n- `dart analyze --fatal-infos` is clean here and in `mcp_examples` resolved against this branch. The diff only adds lines, so existing formatting is untouched.\n\nPart of #162."
    },
    {
      "commit": "4cde5c9df356fc8f68cac8b80186f2ba380f0fcd",
      "tree": "fededc0ebc498c6e48d7c20c15a1eb7f0d077525",
      "parents": [
        "eb0c7b87aa15f8e39ee9f22a38843a90105b3d0f"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Jul 24 08:49:38 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 08:49:38 2026 -0700"
      },
      "message": "Don\u0027t install skills from third_party directories (#563)\n\nSkip recursive crawling into third_party directories when scanning Git repositories for skills.\n\nFixes #553"
    },
    {
      "commit": "eb0c7b87aa15f8e39ee9f22a38843a90105b3d0f",
      "tree": "6bc6ae643b89aecb0ace991d6e99c0993b7f7fcb",
      "parents": [
        "0d0f001065be363916bf1e66a75860219090efa7"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Jul 24 08:32:08 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 08:32:08 2026 -0700"
      },
      "message": "Support hyphens in package name prefixes when matching and creating skills (#566)\n\nFixes #541.\n\n- Support matching package names using hyphens instead of underscores in package name prefixes ( as well as ).\n- Update `skills create` to generate hyphenated package prefixes ().\n- Update documentation and unit tests."
    },
    {
      "commit": "0d0f001065be363916bf1e66a75860219090efa7",
      "tree": "d3e3a86a8b84422d2cb4aec75289a8379a201acd",
      "parents": [
        "857ba4375a0a05b276046a5d6530bf68019643ae"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Jul 24 07:47:48 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 07:47:48 2026 -0700"
      },
      "message": "fix(skills): Do not save repositories in skills add when git clone fails (fixes #561) (#564)\n\nFixes #561\n\n### Description\nIn `skills add`, repositories were previously saved to `GlobalConfig` or local `SkillManifest` files before verification/installation of skills took place. If git clone failed (e.g. invalid repository URL or non-existent remote repository), the invalid repository was still recorded in configuration files, leaving the CLI in a broken state where future commands would continually attempt to sync the non-existent repository.\n\nThis change performs a pre-sync verification check in `AddCommand.run()` prior to updating configuration/manifest files. Any repository that fails to clone or sync is excluded and an error is logged. If all provided repositories fail, `AddCommand` bails out early without saving any entries."
    },
    {
      "commit": "857ba4375a0a05b276046a5d6530bf68019643ae",
      "tree": "2873b7543c82282229796eee722241e7e46556d6",
      "parents": [
        "a1f67a6afc1fb3849e55cb0b35781ce23944e249"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Jul 23 13:06:29 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 13:06:29 2026 -0700"
      },
      "message": "update wording for selection dialogs (#557)\n\nThis should make it more obvious that you won\u0027t be installing all skills, but will be presented with another dialog to choose which skills to install."
    },
    {
      "commit": "a1f67a6afc1fb3849e55cb0b35781ce23944e249",
      "tree": "0c06716c91f329579a5e21f75910c14088ee2b3c",
      "parents": [
        "7d404cf73ed3209c933f4a8f70d6549ab32f0533"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Jul 23 11:11:32 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 11:11:32 2026 -0700"
      },
      "message": "add version flag (#545)\n\nFrom the bug bash, a version flag would have been helpful :)"
    },
    {
      "commit": "7d404cf73ed3209c933f4a8f70d6549ab32f0533",
      "tree": "45665b569a66b7e2cf32c921c44d91a6e023641d",
      "parents": [
        "7ee46a3002cd271939388f8a1b8394e58519744d"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Jul 23 10:29:04 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 10:29:04 2026 -0700"
      },
      "message": "Fix skills create description escaping (#547)\n\nJust JSON encode the descriptions, Yaml is a superset of JSON so this should be sufficient.\n\nFixes #542"
    },
    {
      "commit": "7ee46a3002cd271939388f8a1b8394e58519744d",
      "tree": "fd761990d361e2f44ffd21ce7c31ffd286dc3422",
      "parents": [
        "5b2b8351d6e894ef41efec1e3f50dc493d5b1ea0"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Jul 23 09:24:12 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 09:24:12 2026 -0700"
      },
      "message": "use the dart/workspace/analysis/complete request where possible (#544)\n\nCloses https://github.com/dart-lang/ai/issues/536\nCloses https://github.com/dart-lang/ai/issues/499\n\nAlso preps for a release, we have a decent chunk of functionality ready now.\n\ncc @DanTup"
    },
    {
      "commit": "5b2b8351d6e894ef41efec1e3f50dc493d5b1ea0",
      "tree": "3b8e35d4d4a81cf170097baf221970d4a9a2dafa",
      "parents": [
        "85a5da7f54e9205a18f19e3502394c068750f77e"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Jul 23 09:02:34 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 09:02:34 2026 -0700"
      },
      "message": "use parseDartSDKVersion from unified_analytics (#538)\n\nThis might resolve https://github.com/dart-lang/ai/issues/537, or we might need to actually update the helper, it isn\u0027t clear to me that it will actually resolve the issue looking at the implementation."
    }
  ],
  "next": "85a5da7f54e9205a18f19e3502394c068750f77e"
}
