# Changelog

## 0.1.15 - 2026-09-11

- Add opt-in headless re-login for bot accounts that use TOTP two-factor authentication. When `VRCHAT_MCP_USERNAME`, `VRCHAT_MCP_PASSWORD`, and `VRCHAT_MCP_TOTP_SECRET` are all set, an authenticated request that returns HTTP 401 triggers one automatic login with a locally generated TOTP code, and the original request is retried exactly once. Accounts that use email two-factor authentication are never logged in automatically.
- Guard automatic login with a record persisted beside the cookie file so separately spawned processes share it: at most one attempt every 10 minutes, a 60-minute backoff after a failed or unfinished attempt, and no attempt at all if the record cannot be written. The memory cookie store falls back to a weaker per-process guard.
- Run headless and interactive `vrchat_auth_begin` logins through one queue so their cookie, status, and persistence updates cannot interleave. Credentials, the TOTP secret, generated codes, and cookie values never appear in errors or logs.
- Refresh generated schemas and the tool catalog from community specification v1.20.9. Use `LimitedWorld` for world search, correct multiline Zod record conversion and the empty-notification branch so populated payloads survive parsing, and remove workarounds the specification now resolves.
- Preserve canonical group-post `roleIds` during partial edits, forward the favorite-group type filter, and require explicit series intent for recurring event creates. Event updates fetch the event and check its kind first, schedule replacement is limited to verified series parents, and clearing recurrence with `null` is rejected locally.

## 0.1.14 - 2026-09-08

- Add `vrchat_gallery_images` to list the signed-in account's complete gallery with compact file metadata and a total count. Fetch pages internally, deduplicate file IDs, and retry transient read failures with bounded attempts and per-page deadlines.
- Add individually grantable `vrchat_gallery_image_delete` to delete one exact gallery file after verifying current-account ownership and the gallery tag under the existing write guard. Deletion is single-attempt; callers remain responsible for preserving images referenced by posts, events, or other consumers.
- Keep existing generic file operations available for their broader uses. Gallery-only deployments should grant the curated tool without granting generic or raw file access.

## 0.1.13 - 2026-09-01

- **Breaking:** replace `vrchat_group_image_upload` with the strict account-scoped `vrchat_gallery_image_upload`. The upload endpoint creates a file in the signed-in user's personal gallery and has no group authorization relationship, so the old group-scoped contract has been removed rather than retained as a deprecated alias.
- Migrate callers to the exact `{ imagePath }` input. Remove `groupId`, `shortCode`, and every other extra field because the new schema rejects unknown fields. The result no longer includes `status`, `groupId`, or the nested `file` object. `fileId` remains required and top-level; the former `file.ownerId`, `file.name`, `file.mimeType`, `file.extension`, and `file.version` metadata move to optional top-level fields. See `docs/curated-tools.md` for the complete before-and-after contract.
- Keep the existing write guard, configured upload-root containment, static-PNG validation, multipart `tag=gallery` transport, bounded response metadata, and indeterminate-failure protection. Group post and event tools continue enforcing their own group allowlists before attaching an uploaded file ID.

## 0.1.12 - 2026-09-01

- Add individually grantable `vrchat_group_image_upload` for uploading a validated static PNG to the signed-in account gallery without attaching it to a group post or event. The supplied group is an authorization boundary, not the upload destination.
- Require the write guard, resolved group allowlist, and absolute `uploads.allowedRoots` containment before local file intake; reject symbolic links, junction escapes, replacement races, malformed PNGs, APNG, compressed-profile, excessive-chunk, and IDAT decompression bombs, width or height outside 65 through 2048 pixels inclusive, and files over 10 MiB. Treat upload transport failures as indeterminate and do not retry automatically because the upstream write may already have succeeded; reconcile the gallery before retrying.
- Keep both generic image upload operations out of raw and generated write surfaces, and use the verified multipart `POST /file/image` route only through the curated tool.

## 0.1.11 - 2026-09-01

- Add curated `vrchat_instance_link_event` for linking an existing group instance to a group calendar event through VRChat's undocumented live `PUT /instances/{worldId}:{instanceId}` endpoint.
- Require the configured group allowlist plus matching event and instance ownership, serialize same-instance links, refuse non-group instances and replacement of a different existing link, and keep the broader instance-update body unreachable through raw and generated write tools.
- Return the group ID and readable event and instance labels, and invalidate affected caches on linked, idempotent, and conflicting-link results.
- Record the live six-hour link window and the observed unlink behavior without exposing unlink in the curated tool.
- Reject `canRequestInvite: true` for non-private instances before VRChat returns a 400, while continuing to support omitted and false values for group instances.
- Accept the live `occurrenceKind: "single"` response when `vrchat_event_delete` verifies a `single_event` target, while continuing to fail closed for unknown event kinds.

## 0.1.10 - 2026-08-03

- Add curated `vrchat_avatar_update` for avatar metadata: `name`, `description`, `releaseStatus`, and content tags. Content tags previously had no write path at all.
- Keep avatar asset fields unreachable. `assetUrl`, `unityPackageUrl`, `unityVersion`, and `version` can repoint an avatar at the wrong build with no undo, so `updateAvatar` is curated-only: the raw call tool and the generated write registry both still refuse it, and `createAvatar`/`deleteAvatar` stay blocked outright.
- Merge avatar tags against a freshly-read list instead of replacing them, since `updateAvatar` overwrites the whole array and a blind write would drop author tags. `addTags`/`removeTags` are explicit, `clearContentTags` strips every `content_*` tag including ones newer than this build, and concurrent updates to one avatar are serialized so neither loses the other's addition.
- Target an avatar by `avtr_` ID or by the exact name of one of your own avatars, paging through every owned avatar before deciding and refusing with the candidate IDs rather than guessing when a name is ambiguous.
- Fix login being impossible from any browser: the auth page sent `Referrer-Policy: no-referrer`, which makes a non-CORS form POST serialize `Origin` as `null`, and the page's own loopback origin check then rejected it.
- Fix `getGroup` throwing for any group with no pending ownership transfer, where `transferTargetId` comes back `null` against a strict string schema.
- Fix `vrchat_status_set` mapping `color: "blue"` to `active`. Blue is Join Me in the VRChat client; green is Active.
- Fix user invites sending a stripped instance ID. `POST /invite/{userId}` requires the full `worldId:instanceId` location and answers `400: Invalid location` otherwise, which affected `vrchat_invite_user_to_me`, `here=true`, and `worldId + instanceId` calls.
- Fix `vrchat_group_roles_manage` advertising a schema with no properties, so typed fields such as `permissions` never reached the wire contract and arrived as strings. Every argument now carries a description, including which action requires it.
- Refresh the `GroupPermissions` enum: the live API returns 27 permissions and the vendored spec listed 25, so role updates using `group-instance-announcement-create` or `group-instance-bypass-avatar-performance` failed validation before reaching VRChat.
- Add `docs/spec-drift.md`, a log of observed divergences between the community OpenAPI spec and the live API, with the standing rule that the live API is the source of truth and entries must be re-verified before being relied on.
- **Breaking:** a bare instance ID is no longer accepted as an invite destination. VRChat rejects it, so `vrchat_invite` and `vrchat_invite_user` now require `here=true`, a full `wrld_:instance` location, or `worldId` + `instanceId`.

## 0.1.9 - 2026-07-31

- Add curated `vrchat_group_post_create`, `vrchat_group_post_update`, and `vrchat_group_post_delete` so a tool-filtered deployment can grant group posting without granting every other write.
- Keep group posts quiet by default: both create and update require an explicit `sendNotification` opt-in before members are pinged.
- Fill omitted fields on `vrchat_group_post_update` from the current post, since VRChat replaces the whole post on edit. The lookup always runs, so an edit never silently drops `roleIds` or `imageId`; pass `roleIds: []` to clear role restrictions deliberately. Posts older than the 300-post lookup window can still be replaced outright by supplying `title`, `text`, and `visibility`, which reports `mergedFromExisting: false`.
- Reject a `vrchat_group_post_update` call that changes no fields, so an unchanged post cannot have its timestamp bumped or its members re-notified.
- Invalidate cached group reads after every post write, including when the write succeeds but its response fails to parse, so `vrchat_group_posts_recent` does not serve a stale list and a retry cannot double-post.
- Include `roleIds` and `imageId` in group post summaries so read-then-edit flows no longer drop role restrictions or attached images.
- Accept `shortCode` as well as `groupId` on all three group post tools, resolving it before the `groups.allowlist` check.
- Support removing a post image with `imageId: null` on update, which was otherwise unreachable once the curated tools replaced the generated `updateGroupPost`.
- Reject an update whose supplied values already match the post, instead of re-sending identical content and possibly re-notifying members.
- Report success when a post write lands but its response cannot be parsed, since neither create nor update is idempotent and a retry would post and notify twice.
- **Breaking:** `addGroupPost`, `updateGroupPost`, and `deleteGroupPost` now resolve to the curated tools above and are no longer reachable through `vrchat_write` or `vrchat_delete`, even when listed in `generatedWriteTools.operationIds`.

## 0.1.8 - 2026-07-24

- Add opt-in, loopback-only MCP Streamable HTTP alongside the default stdio transport.
- Protect HTTP with required bearer authentication, Host and Origin validation, bounded sessions, abandoned-session cleanup, request rate and body limits, and graceful shutdown.
- Track resource subscriptions per MCP session and fan VRChat pipeline updates out to every subscribed client.
- Add HTTP configuration, CLI options, documentation, multi-session end-to-end coverage, and compatible production dependency security updates.
- Make `vrchat_group_members` return one bounded page by default and require `view: "all"` for complete snapshots.
- Pace, retry, cache, and cap full group-member snapshots at 10,000 members without publishing interrupted scans as complete.

## 0.1.7 - 2026-06-13

- Refresh dependency locks for Hono, Undici, esbuild, and Node type patch updates.
- Raise the direct Undici and Node type dependency minimums to the refreshed patch versions.

## 0.1.6 - 2026-06-03

- Fix local browser auth submissions from same-port loopback aliases such as `localhost`.
- Keep auth Host and Origin validation strict for non-loopback, wrong-port, non-HTTP, and userinfo-shaped inputs.
- Keep live status-page e2e coverage opt-in so release CI does not depend on transient external status-page availability.

## 0.1.5 - 2026-05-19

- Correct the MCP Registry package metadata so the npm package entry points at the published release version.

## 0.1.4 - 2026-05-18

- Default authentication cookie storage to the OS keychain, with file storage fallback when the keychain backend is unavailable.
- Rewrite the README around consumer install paths, client-specific MCP config, login, and core tools.

## 0.1.3 - 2026-05-17

- Simplify registry-visible configuration to the common user-facing environment variables.
- Keep low-level cache, pipeline, and group allowlist tuning in JSON config instead of environment variables.
- `VRCHAT_MCP_GROUP_ALLOWLIST` remains honored for compatibility; prefer `groups.allowlist` in `VRCHAT_MCP_CONFIG_FILE` for new setups.
- Enable write tools by default; set `writes.allow=false` or `VRCHAT_MCP_ALLOW_WRITES=false` for read-only mode.

## 0.1.2 - 2026-05-16

- Match MCP Registry server namespace casing to the GitHub organization namespace authorized by registry login.

## 0.1.1 - 2026-05-16

- Add MCP Registry metadata and npm ownership marker for registry publication.
- Move the documented and CI runtime baseline to Node.js 24.15.0, the current LTS baseline used for release validation.

## 0.1.0 - 2026-05-15

Initial public release.

- MCP tools for VRChat friends, worlds, groups, events, notifications, status, avatars, and VRCX history.
- Local browser login flow with configurable cookie storage.
- Read-only defaults with explicit write opt-in and group write allowlists.
- Curated tools for common workflows plus generated tools from the VRChat OpenAPI spec.
- Local resources for friend snapshots and friend change deltas.
- Mock E2E coverage, opt-in live smoke checks, and generated tool catalog docs.
