@basicbit/vrchat-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +266 -0
  4. package/assets/logo.svg +39 -0
  5. package/dist/bin/cli.js +4 -0
  6. package/dist/bin/cli.js.map +1 -0
  7. package/dist/package.json +109 -0
  8. package/dist/src/auth/cookieStore.js +136 -0
  9. package/dist/src/auth/cookieStore.js.map +1 -0
  10. package/dist/src/auth/index.js +398 -0
  11. package/dist/src/auth/index.js.map +1 -0
  12. package/dist/src/config/defaults.json +58 -0
  13. package/dist/src/config/index.js +405 -0
  14. package/dist/src/config/index.js.map +1 -0
  15. package/dist/src/core/client.js +262 -0
  16. package/dist/src/core/client.js.map +1 -0
  17. package/dist/src/core/generatedToolOverrides.js +104 -0
  18. package/dist/src/core/generatedToolOverrides.js.map +1 -0
  19. package/dist/src/core/generatedToolSkips.js +28 -0
  20. package/dist/src/core/generatedToolSkips.js.map +1 -0
  21. package/dist/src/core/operationSchemas.js +102 -0
  22. package/dist/src/core/operationSchemas.js.map +1 -0
  23. package/dist/src/core/readToolRegistry.js +93 -0
  24. package/dist/src/core/readToolRegistry.js.map +1 -0
  25. package/dist/src/core/readTools.js +197 -0
  26. package/dist/src/core/readTools.js.map +1 -0
  27. package/dist/src/core/spec.js +137 -0
  28. package/dist/src/core/spec.js.map +1 -0
  29. package/dist/src/core/writeToolRegistry.js +113 -0
  30. package/dist/src/core/writeToolRegistry.js.map +1 -0
  31. package/dist/src/generated/vrchat-schemas.js +3326 -0
  32. package/dist/src/generated/vrchat-schemas.js.map +1 -0
  33. package/dist/src/index.js +31 -0
  34. package/dist/src/index.js.map +1 -0
  35. package/dist/src/infra/logger.js +26 -0
  36. package/dist/src/infra/logger.js.map +1 -0
  37. package/dist/src/models/avatars.js +22 -0
  38. package/dist/src/models/avatars.js.map +1 -0
  39. package/dist/src/models/events.js +115 -0
  40. package/dist/src/models/events.js.map +1 -0
  41. package/dist/src/models/friends.js +148 -0
  42. package/dist/src/models/friends.js.map +1 -0
  43. package/dist/src/models/groups.js +228 -0
  44. package/dist/src/models/groups.js.map +1 -0
  45. package/dist/src/models/instances.js +56 -0
  46. package/dist/src/models/instances.js.map +1 -0
  47. package/dist/src/models/invites.js +34 -0
  48. package/dist/src/models/invites.js.map +1 -0
  49. package/dist/src/models/notifications.js +62 -0
  50. package/dist/src/models/notifications.js.map +1 -0
  51. package/dist/src/models/status.js +50 -0
  52. package/dist/src/models/status.js.map +1 -0
  53. package/dist/src/models/statusPage.js +84 -0
  54. package/dist/src/models/statusPage.js.map +1 -0
  55. package/dist/src/models/users.js +113 -0
  56. package/dist/src/models/users.js.map +1 -0
  57. package/dist/src/models/vrcx.js +144 -0
  58. package/dist/src/models/vrcx.js.map +1 -0
  59. package/dist/src/models/worlds.js +150 -0
  60. package/dist/src/models/worlds.js.map +1 -0
  61. package/dist/src/resources/friendsChanges.js +44 -0
  62. package/dist/src/resources/friendsChanges.js.map +1 -0
  63. package/dist/src/resources/friendsSnapshot.js +69 -0
  64. package/dist/src/resources/friendsSnapshot.js.map +1 -0
  65. package/dist/src/resources/index.js +9 -0
  66. package/dist/src/resources/index.js.map +1 -0
  67. package/dist/src/resources/subscriptions.js +39 -0
  68. package/dist/src/resources/subscriptions.js.map +1 -0
  69. package/dist/src/schemas/auth.js +3 -0
  70. package/dist/src/schemas/auth.js.map +1 -0
  71. package/dist/src/schemas/call.js +13 -0
  72. package/dist/src/schemas/call.js.map +1 -0
  73. package/dist/src/schemas/read.js +58 -0
  74. package/dist/src/schemas/read.js.map +1 -0
  75. package/dist/src/schemas/write.js +18 -0
  76. package/dist/src/schemas/write.js.map +1 -0
  77. package/dist/src/services/api/client.js +66 -0
  78. package/dist/src/services/api/client.js.map +1 -0
  79. package/dist/src/services/api/index.js +2 -0
  80. package/dist/src/services/api/index.js.map +1 -0
  81. package/dist/src/services/avatars/index.js +24 -0
  82. package/dist/src/services/avatars/index.js.map +1 -0
  83. package/dist/src/services/cache.js +158 -0
  84. package/dist/src/services/cache.js.map +1 -0
  85. package/dist/src/services/events/curated.js +229 -0
  86. package/dist/src/services/events/curated.js.map +1 -0
  87. package/dist/src/services/events/index.js +3 -0
  88. package/dist/src/services/events/index.js.map +1 -0
  89. package/dist/src/services/events/utils.js +75 -0
  90. package/dist/src/services/events/utils.js.map +1 -0
  91. package/dist/src/services/friends/changes.js +246 -0
  92. package/dist/src/services/friends/changes.js.map +1 -0
  93. package/dist/src/services/friends/curated.js +497 -0
  94. package/dist/src/services/friends/curated.js.map +1 -0
  95. package/dist/src/services/friends/fetch.js +69 -0
  96. package/dist/src/services/friends/fetch.js.map +1 -0
  97. package/dist/src/services/friends/index.js +5 -0
  98. package/dist/src/services/friends/index.js.map +1 -0
  99. package/dist/src/services/friends/match.js +98 -0
  100. package/dist/src/services/friends/match.js.map +1 -0
  101. package/dist/src/services/groups/allowlist.js +19 -0
  102. package/dist/src/services/groups/allowlist.js.map +1 -0
  103. package/dist/src/services/groups/curated.js +343 -0
  104. package/dist/src/services/groups/curated.js.map +1 -0
  105. package/dist/src/services/groups/index.js +3 -0
  106. package/dist/src/services/groups/index.js.map +1 -0
  107. package/dist/src/services/instances/curated.js +80 -0
  108. package/dist/src/services/instances/curated.js.map +1 -0
  109. package/dist/src/services/instances/index.js +3 -0
  110. package/dist/src/services/instances/index.js.map +1 -0
  111. package/dist/src/services/instances/read.js +14 -0
  112. package/dist/src/services/instances/read.js.map +1 -0
  113. package/dist/src/services/invites/curated.js +90 -0
  114. package/dist/src/services/invites/curated.js.map +1 -0
  115. package/dist/src/services/invites/index.js +2 -0
  116. package/dist/src/services/invites/index.js.map +1 -0
  117. package/dist/src/services/notifications/curated.js +54 -0
  118. package/dist/src/services/notifications/curated.js.map +1 -0
  119. package/dist/src/services/notifications/index.js +2 -0
  120. package/dist/src/services/notifications/index.js.map +1 -0
  121. package/dist/src/services/pipeline/events.js +40 -0
  122. package/dist/src/services/pipeline/events.js.map +1 -0
  123. package/dist/src/services/pipeline/handlers.js +21 -0
  124. package/dist/src/services/pipeline/handlers.js.map +1 -0
  125. package/dist/src/services/pipeline/index.js +4 -0
  126. package/dist/src/services/pipeline/index.js.map +1 -0
  127. package/dist/src/services/pipeline/manager.js +143 -0
  128. package/dist/src/services/pipeline/manager.js.map +1 -0
  129. package/dist/src/services/status/curated.js +53 -0
  130. package/dist/src/services/status/curated.js.map +1 -0
  131. package/dist/src/services/status/index.js +2 -0
  132. package/dist/src/services/status/index.js.map +1 -0
  133. package/dist/src/services/statusPage/curated.js +397 -0
  134. package/dist/src/services/statusPage/curated.js.map +1 -0
  135. package/dist/src/services/statusPage/index.js +2 -0
  136. package/dist/src/services/statusPage/index.js.map +1 -0
  137. package/dist/src/services/users/curated.js +124 -0
  138. package/dist/src/services/users/curated.js.map +1 -0
  139. package/dist/src/services/users/groups.js +54 -0
  140. package/dist/src/services/users/groups.js.map +1 -0
  141. package/dist/src/services/users/index.js +3 -0
  142. package/dist/src/services/users/index.js.map +1 -0
  143. package/dist/src/services/vrcx/db.js +13 -0
  144. package/dist/src/services/vrcx/db.js.map +1 -0
  145. package/dist/src/services/vrcx/gamelog.js +125 -0
  146. package/dist/src/services/vrcx/gamelog.js.map +1 -0
  147. package/dist/src/services/vrcx/index.js +5 -0
  148. package/dist/src/services/vrcx/index.js.map +1 -0
  149. package/dist/src/services/vrcx/memos.js +51 -0
  150. package/dist/src/services/vrcx/memos.js.map +1 -0
  151. package/dist/src/services/vrcx/paths.js +133 -0
  152. package/dist/src/services/vrcx/paths.js.map +1 -0
  153. package/dist/src/services/vrcx/relationships.js +138 -0
  154. package/dist/src/services/vrcx/relationships.js.map +1 -0
  155. package/dist/src/services/vrcx/shared.js +173 -0
  156. package/dist/src/services/vrcx/shared.js.map +1 -0
  157. package/dist/src/services/vrcx/status.js +54 -0
  158. package/dist/src/services/vrcx/status.js.map +1 -0
  159. package/dist/src/services/worlds/index.js +256 -0
  160. package/dist/src/services/worlds/index.js.map +1 -0
  161. package/dist/src/tools/auth.js +44 -0
  162. package/dist/src/tools/auth.js.map +1 -0
  163. package/dist/src/tools/cache.js +61 -0
  164. package/dist/src/tools/cache.js.map +1 -0
  165. package/dist/src/tools/curated/avatars.js +57 -0
  166. package/dist/src/tools/curated/avatars.js.map +1 -0
  167. package/dist/src/tools/curated/events.js +212 -0
  168. package/dist/src/tools/curated/events.js.map +1 -0
  169. package/dist/src/tools/curated/friends.js +168 -0
  170. package/dist/src/tools/curated/friends.js.map +1 -0
  171. package/dist/src/tools/curated/groups.js +368 -0
  172. package/dist/src/tools/curated/groups.js.map +1 -0
  173. package/dist/src/tools/curated/instances.js +35 -0
  174. package/dist/src/tools/curated/instances.js.map +1 -0
  175. package/dist/src/tools/curated/invites.js +78 -0
  176. package/dist/src/tools/curated/invites.js.map +1 -0
  177. package/dist/src/tools/curated/notifications.js +35 -0
  178. package/dist/src/tools/curated/notifications.js.map +1 -0
  179. package/dist/src/tools/curated/status.js +44 -0
  180. package/dist/src/tools/curated/status.js.map +1 -0
  181. package/dist/src/tools/curated/statusPage.js +27 -0
  182. package/dist/src/tools/curated/statusPage.js.map +1 -0
  183. package/dist/src/tools/curated/users.js +201 -0
  184. package/dist/src/tools/curated/users.js.map +1 -0
  185. package/dist/src/tools/curated/vrcx/gamelog.js +80 -0
  186. package/dist/src/tools/curated/vrcx/gamelog.js.map +1 -0
  187. package/dist/src/tools/curated/vrcx/index.js +11 -0
  188. package/dist/src/tools/curated/vrcx/index.js.map +1 -0
  189. package/dist/src/tools/curated/vrcx/memos.js +105 -0
  190. package/dist/src/tools/curated/vrcx/memos.js.map +1 -0
  191. package/dist/src/tools/curated/vrcx/relationships.js +86 -0
  192. package/dist/src/tools/curated/vrcx/relationships.js.map +1 -0
  193. package/dist/src/tools/curated/vrcx/status.js +43 -0
  194. package/dist/src/tools/curated/vrcx/status.js.map +1 -0
  195. package/dist/src/tools/curated/worlds.js +162 -0
  196. package/dist/src/tools/curated/worlds.js.map +1 -0
  197. package/dist/src/tools/generated.js +19 -0
  198. package/dist/src/tools/generated.js.map +1 -0
  199. package/dist/src/tools/raw.js +49 -0
  200. package/dist/src/tools/raw.js.map +1 -0
  201. package/dist/src/tools/read/common.js +58 -0
  202. package/dist/src/tools/read/common.js.map +1 -0
  203. package/dist/src/tools/read/system.js +19 -0
  204. package/dist/src/tools/read/system.js.map +1 -0
  205. package/dist/src/tools/registerAllTools.js +41 -0
  206. package/dist/src/tools/registerAllTools.js.map +1 -0
  207. package/dist/src/tools/write/common.js +10 -0
  208. package/dist/src/tools/write/common.js.map +1 -0
  209. package/dist/src/utils/json.js +53 -0
  210. package/dist/src/utils/json.js.map +1 -0
  211. package/dist/src/utils/schema.js +14 -0
  212. package/dist/src/utils/schema.js.map +1 -0
  213. package/dist/src/utils/stableStringify.js +36 -0
  214. package/dist/src/utils/stableStringify.js.map +1 -0
  215. package/dist/src/utils/strings.js +7 -0
  216. package/dist/src/utils/strings.js.map +1 -0
  217. package/dist/src/utils/toolAnnotations.js +17 -0
  218. package/dist/src/utils/toolAnnotations.js.map +1 -0
  219. package/dist/src/utils/toolNames.js +13 -0
  220. package/dist/src/utils/toolNames.js.map +1 -0
  221. package/dist/src/utils/toolResponses.js +12 -0
  222. package/dist/src/utils/toolResponses.js.map +1 -0
  223. package/docs/architecture.md +46 -0
  224. package/docs/curated-tools.md +132 -0
  225. package/docs/design-notes.md +48 -0
  226. package/docs/evals.md +129 -0
  227. package/docs/tools-guide.md +27 -0
  228. package/docs/tools.md +13849 -0
  229. package/docs/vrcx.md +69 -0
  230. package/package.json +109 -0
@@ -0,0 +1,132 @@
1
+ # Curated Tool Charter
2
+
3
+ This document defines the curated tool surface. The goal is to keep the
4
+ default toolset small, explicit, and task-oriented so MCP clients can choose the next call
5
+ without wading through hundreds of low-level endpoints.
6
+
7
+ ## Principles
8
+
9
+ - Small and explicit: each tool has a single, obvious purpose.
10
+ - Human-input friendly: accept names or natural inputs where reasonable.
11
+ - Composable: outputs include IDs and metadata for follow-ups.
12
+ - Safe by default: write tools are opt-in via `writes.allow`, with group allowlists for group-scoped writes.
13
+
14
+ ## Write controls
15
+
16
+ - Read-only tools are always enabled.
17
+ - Write tools require `writes.allow = true`.
18
+ - Group-scoped writes additionally honor `groups.allowlist`.
19
+
20
+ ## Current curated tools (implemented)
21
+
22
+ Friends and social (read):
23
+
24
+ - `vrchat_friends_search`
25
+ - `vrchat_friend_details`
26
+ - `vrchat_friends_list`
27
+ - `vrchat_friends_overview`
28
+
29
+ Users and groups (read):
30
+
31
+ - `vrchat_me`
32
+ - `vrchat_user_profile`
33
+ - `vrchat_user_groups`
34
+
35
+ Avatars (read):
36
+
37
+ - `vrchat_avatar_profile`
38
+
39
+ Groups and updates (read):
40
+
41
+ - `vrchat_groups_search`
42
+ - `vrchat_group_profile`
43
+ - `vrchat_group_members`
44
+ - `vrchat_group_posts_recent`
45
+ - `vrchat_group_events_list`
46
+ - `vrchat_group_event_get`
47
+ - `vrchat_group_events_upcoming`
48
+ - `vrchat_group_instances_overview`
49
+
50
+ Worlds (read):
51
+
52
+ - `vrchat_worlds_search`
53
+ - `vrchat_worlds_favorites`
54
+ - `vrchat_world_profile`
55
+ - `vrchat_world_instances_overview`
56
+
57
+ Status and presence:
58
+
59
+ - `vrchat_status_get` (read)
60
+ - `vrchat_status_set` (low-risk write)
61
+ - `vrchat_profile_update` (profile write; status preserved automatically)
62
+
63
+ Status page (read):
64
+
65
+ - `vrchat_status_page_overview`
66
+
67
+ Notifications (read):
68
+
69
+ - `vrchat_notifications_recent`
70
+
71
+ Local VRCX (read, optional):
72
+
73
+ - `vrcx_db_status`
74
+ - `vrcx_memos_user_get`
75
+ - `vrcx_memos_world_get`
76
+ - `vrcx_memos_avatar_get`
77
+ - `vrcx_gamelog_world_visits_recent`
78
+ - `vrcx_instances_recent`
79
+ - `vrcx_user_relationship_summary`
80
+ - `vrcx_user_relationship_sessions`
81
+
82
+ Events and calendar (read):
83
+
84
+ - `vrchat_events_upcoming`
85
+ - `vrchat_events_search`
86
+
87
+ Events and calendar (write):
88
+
89
+ - `vrchat_event_create`
90
+ - `vrchat_event_update`
91
+ - `vrchat_event_delete`
92
+
93
+ Instances and invites (write):
94
+
95
+ - `vrchat_instance_create`
96
+ - `vrchat_invite_user`
97
+
98
+ Invites (write, low-risk):
99
+
100
+ - `vrchat_invite_self`
101
+
102
+ ## Next up (near-term)
103
+
104
+ Groups (read):
105
+
106
+ - `vrchat_group_members_summary`
107
+ - `vrchat_groups_overview`
108
+
109
+ Notifications (read):
110
+
111
+ - `vrchat_notifications_unread`
112
+
113
+ ## Later (optional)
114
+
115
+ Invites:
116
+
117
+ - `vrchat_invites_pending`
118
+ - `vrchat_invite_accept` (medium-risk)
119
+
120
+ Automation hooks:
121
+
122
+ - `vrchat_status_guard` (periodic check + corrective update)
123
+
124
+ ## Toolset toggles (planned)
125
+
126
+ Auto-generated read tools are enabled by default (`vrchat_read_<operationId>`).
127
+ Auto-generated write tools are enabled by default (`vrchat_write_<operationId>`, gated by `writes.allow`).
128
+ The raw tool (`vrchat_call`) is disabled by default and can be enabled via config/environment flags.
129
+
130
+ ## Group allowlist guard
131
+
132
+ Use `groups.allowlist` in the config file to limit group write operations to specific group IDs.
@@ -0,0 +1,48 @@
1
+ # Design Notes (Archived)
2
+
3
+ These notes capture ideas and decisions from early planning docs. Items here are
4
+ either future-facing or contextual and are not required to run the MCP today.
5
+
6
+ ## Tool ergonomics
7
+
8
+ - Prefer curated tools with clear, single-purpose effects.
9
+ - Favor name-based inputs for human-friendly lookup; return IDs for follow-ups.
10
+ - Automatically unroll pagination for “get all” domains (friends, groups) unless
11
+ the user explicitly wants page-based browsing (e.g., world search).
12
+ - Keep outputs compact and task-oriented; avoid dumping large, low-signal fields.
13
+
14
+ ## Safety + scope (future-facing)
15
+
16
+ - Hard deny: account deletion should never be exposed.
17
+ - Dangerous actions (world/group deletion, moderation actions) should remain
18
+ off by default; if ever enabled, require explicit opt-in and strong warnings.
19
+ - Optional “read-only vs power-user” profiles may be useful later (not implemented).
20
+
21
+ ## Realtime + caching
22
+
23
+ - Pipeline websocket should update caches and drive MCP resources.
24
+ - Prefer resources + subscriptions over custom notifications for live updates.
25
+ - Stale-while-revalidate for heavy list endpoints (friends, groups) is desired.
26
+
27
+ ## Friends overview (location-centric)
28
+
29
+ - Group online friends by instance/location to mirror VRChat’s social tab.
30
+ - Include instance details per location (summary by default, full optional).
31
+ - Use deduped instance/group/world lookups to keep output compact.
32
+ - Support optional filters like status + minimum instance user count.
33
+
34
+ ## Groups + notifications
35
+
36
+ - Prefer group posts as the primary “updates” feed; announcements are singular.
37
+ - Use upcoming-window semantics for group events (e.g., next 7 days).
38
+ - Keep group profile separate from heavy lists (members/posts/instances).
39
+
40
+ ## Evals (opt-in)
41
+
42
+ - LLM-as-judge evals for curated tool outputs are valuable but optional.
43
+ - Mock mode should be deterministic; live mode should be opt-in with real creds.
44
+ - Sources to revisit if needed:
45
+ - https://platform.openai.com/docs/guides/graders
46
+ - https://platform.openai.com/docs/guides/structured-outputs
47
+ - https://www.promptfoo.dev/docs/intro/
48
+ - https://docs.ragas.io/
package/docs/evals.md ADDED
@@ -0,0 +1,129 @@
1
+ # Evals
2
+
3
+ This project uses three evaluation loops, from cheapest to most realistic.
4
+
5
+ ## 1. Mock LLM Evals
6
+
7
+ Use this when changing tool outputs, schemas, or response wording.
8
+
9
+ ```bash
10
+ npm run test:evals
11
+ ```
12
+
13
+ These tests run against the mock VRChat server and grade expected facts with an LLM. They are deterministic enough for CI-style regression checks, but they do not prove live VRChat behavior.
14
+
15
+ ## 2. Read-Only Live Smoke
16
+
17
+ Use this after login changes, curated tool changes, or OpenAPI/spec parameter changes.
18
+
19
+ ```bash
20
+ npm run build
21
+ npm run smoke:live
22
+ ```
23
+
24
+ The smoke script starts the built MCP server, uses file cookie storage by default, and calls representative read tools across auth, profile, friends, worlds, groups, events, notifications, status page, and VRCX.
25
+
26
+ Useful optional targets:
27
+
28
+ ```bash
29
+ VRCHAT_MCP_SMOKE_FRIEND_NAME="Display Name" npm run smoke:live
30
+ VRCHAT_MCP_SMOKE_WORLD_QUERY="club" npm run smoke:live
31
+ VRCHAT_MCP_SMOKE_GROUP_ID="grp_..." npm run smoke:live
32
+ ```
33
+
34
+ Expected result shape:
35
+
36
+ ```json
37
+ {
38
+ "passed": 29,
39
+ "warned": 0,
40
+ "failed": 0,
41
+ "results": []
42
+ }
43
+ ```
44
+
45
+ Warnings are acceptable for optional VRCX or private group data. Failures need investigation before shipping.
46
+
47
+ ## 3. Manual Agent Evals
48
+
49
+ Use this for the checks that catch tool-routing problems: connect Claude/OpenCode to the MCP server and ask for real VRChat lookups. Watch whether the client chooses the right tools, follows IDs from prior results, handles empty results, and asks for confirmation before writes.
50
+
51
+ Good read-only prompts:
52
+
53
+ ```text
54
+ Who is online right now, grouped by world, and where are the largest clusters of my friends?
55
+ ```
56
+
57
+ ```text
58
+ Find a friend named <name>, tell me where they are, and include the world/group IDs I would need for follow-up actions.
59
+ ```
60
+
61
+ ```text
62
+ Find upcoming events for group <group name or ID> this week. Pick the next one and show the event details.
63
+ ```
64
+
65
+ ```text
66
+ Search for worlds matching "club" and summarize three good candidates without dumping tags unless useful.
67
+ ```
68
+
69
+ ```text
70
+ Show recent notifications and tell me which ones look actionable.
71
+ ```
72
+
73
+ Good write-flow prompts, only with `writes.allow=true` and disposable targets:
74
+
75
+ ```text
76
+ Create a private instance in <world name> for me, then invite only me to it.
77
+ ```
78
+
79
+ ```text
80
+ Invite <friend name> to my current instance, but ask me for confirmation before sending anything.
81
+ ```
82
+
83
+ ```text
84
+ Set my VRChat status description to a test value, confirm it changed, then set it back.
85
+ ```
86
+
87
+ Manual pass criteria:
88
+
89
+ - The client uses curated tools before raw/generated tools when a curated tool exists.
90
+ - The client handles names first, then carries IDs forward for follow-up calls.
91
+ - The client treats empty or missing results as a real outcome, not a failure.
92
+ - The client does not expose excessive friend/profile data unless needed for the task.
93
+ - The client asks before medium-risk or externally visible writes.
94
+ - The client explains any VRChat API errors in user terms and suggests the next useful tool.
95
+
96
+ ## Live LLM Evals
97
+
98
+ Live LLM evals are opt-in because they call real VRChat APIs and an LLM grader.
99
+
100
+ Create a live config outside the repository, then point `VRCHAT_MCP_LIVE_CONFIG_FILE` at it. If `cookieFile` is omitted, tests use a per-user config directory such as `%APPDATA%\\vrchat-mcp\\cookies.json` on Windows or `~/.config/vrchat-mcp/cookies.json` on Linux.
101
+
102
+ ```json
103
+ {
104
+ "loginTimeoutSec": 120,
105
+ "debug": false,
106
+ "writeTests": { "enabled": false }
107
+ }
108
+ ```
109
+
110
+ Create an eval config outside the repository, set `OPENAI_API_KEY` in your shell or secret manager, then point `VRCHAT_MCP_EVAL_CONFIG_FILE` at the eval config. Do not put API keys directly in JSON files.
111
+
112
+ You can copy `test/fixtures/evals.live.example.json`; it references `OPENAI_API_KEY` by environment variable name only.
113
+
114
+ Run live evals from PowerShell with:
115
+
116
+ ```powershell
117
+ $env:VRCHAT_MCP_LIVE_CONFIG_FILE = Join-Path $env:APPDATA 'vrchat-mcp\e2e.live.json'
118
+ $env:VRCHAT_MCP_EVAL_CONFIG_FILE = Join-Path $env:APPDATA 'vrchat-mcp\evals.live.json'
119
+ $env:VRCHAT_MCP_ENABLE_LIVE_EVALS = '1'
120
+ npm test -- test/evals/live-llm.test.ts
121
+ ```
122
+
123
+ Run live evals from bash with:
124
+
125
+ ```bash
126
+ VRCHAT_MCP_LIVE_CONFIG_FILE="$HOME/.config/vrchat-mcp/e2e.live.json" VRCHAT_MCP_EVAL_CONFIG_FILE="$HOME/.config/vrchat-mcp/evals.live.json" VRCHAT_MCP_ENABLE_LIVE_EVALS=1 npm test -- test/evals/live-llm.test.ts
127
+ ```
128
+
129
+ If this fails before running test cases with a login error, run `npm run smoke:live` first. Smoke is the cheaper auth/session diagnostic.
@@ -0,0 +1,27 @@
1
+ # Tools Guide
2
+
3
+ This is the human-oriented overview for how to use the tool surface. The full, generated catalog of exposed tools (with schemas) is in `docs/tools.md`.
4
+
5
+ ## How to use tools
6
+
7
+ - Prefer **curated tools** first. They include search and summary flows for common VRChat tasks.
8
+ - Use **auto-generated tools** (`vrchat_read_<operationId>`, `vrchat_write_<operationId>`) only when a curated tool does not exist.
9
+ - **Writes are opt-in**. Set `writes.allow = true` (or `VRCHAT_MCP_ALLOW_WRITES=true`) to enable any non-GET operation.
10
+ - Group write actions are restricted by `groups.allowlist` when set.
11
+
12
+ ## MCP resources
13
+
14
+ - `vrchat://friends/changes{?after,limit}` - delta feed for friend updates.
15
+ - `vrchat://friends/snapshot{?includeOffline,pageSize,maxPages}` - friends snapshot.
16
+
17
+ ## Swagger UI (mcpo)
18
+
19
+ - Run `npm run mcpo` to spin up an OpenAPI proxy with Swagger UI.
20
+ - `npm run mcpo` requires `uvx` (from Astral’s `uv`) to be installed.
21
+ - Open `http://localhost:8000/docs` to browse and try tool calls.
22
+ - For config-based setup (Claude Desktop config + hot reload), see `README.md`.
23
+
24
+ ## Where the truth lives
25
+
26
+ - `docs/tools.md` is generated from code + the OpenAPI spec and reflects the actual exposed tools.
27
+ - `docs/curated-tools.md` describes the curated tool charter and risk tiers.