@remix-gg/mcp 0.4.3

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 (139) hide show
  1. package/README.md +81 -0
  2. package/dist/client-helpers/index.d.ts +2 -0
  3. package/dist/client-helpers/index.d.ts.map +1 -0
  4. package/dist/client-helpers/index.js +2 -0
  5. package/dist/client-helpers/index.js.map +1 -0
  6. package/dist/config.d.ts +20 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +58 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/core/api-client.d.ts +4 -0
  11. package/dist/core/api-client.d.ts.map +1 -0
  12. package/dist/core/api-client.js +12 -0
  13. package/dist/core/api-client.js.map +1 -0
  14. package/dist/core/config.d.ts +6 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/config.js +19 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/core/index.d.ts +5 -0
  19. package/dist/core/index.d.ts.map +1 -0
  20. package/dist/core/index.js +4 -0
  21. package/dist/core/index.js.map +1 -0
  22. package/dist/core/skills.d.ts +22 -0
  23. package/dist/core/skills.d.ts.map +1 -0
  24. package/dist/core/skills.js +49 -0
  25. package/dist/core/skills.js.map +1 -0
  26. package/dist/core/tool-defs.d.ts +12 -0
  27. package/dist/core/tool-defs.d.ts.map +1 -0
  28. package/dist/core/tool-defs.js +356 -0
  29. package/dist/core/tool-defs.js.map +1 -0
  30. package/dist/core/tools/create-game.d.ts +9 -0
  31. package/dist/core/tools/create-game.d.ts.map +1 -0
  32. package/dist/core/tools/create-game.js +21 -0
  33. package/dist/core/tools/create-game.js.map +1 -0
  34. package/dist/core/tools/create-shop-item.d.ts +14 -0
  35. package/dist/core/tools/create-shop-item.d.ts.map +1 -0
  36. package/dist/core/tools/create-shop-item.js +78 -0
  37. package/dist/core/tools/create-shop-item.js.map +1 -0
  38. package/dist/core/tools/delete-shop-item.d.ts +9 -0
  39. package/dist/core/tools/delete-shop-item.d.ts.map +1 -0
  40. package/dist/core/tools/delete-shop-item.js +19 -0
  41. package/dist/core/tools/delete-shop-item.js.map +1 -0
  42. package/dist/core/tools/generate-image.d.ts +8 -0
  43. package/dist/core/tools/generate-image.d.ts.map +1 -0
  44. package/dist/core/tools/generate-image.js +32 -0
  45. package/dist/core/tools/generate-image.js.map +1 -0
  46. package/dist/core/tools/generate-sprite-sheet.d.ts +14 -0
  47. package/dist/core/tools/generate-sprite-sheet.d.ts.map +1 -0
  48. package/dist/core/tools/generate-sprite-sheet.js +29 -0
  49. package/dist/core/tools/generate-sprite-sheet.js.map +1 -0
  50. package/dist/core/tools/helpers.d.ts +60 -0
  51. package/dist/core/tools/helpers.d.ts.map +1 -0
  52. package/dist/core/tools/helpers.js +68 -0
  53. package/dist/core/tools/helpers.js.map +1 -0
  54. package/dist/core/tools/index.d.ts +13 -0
  55. package/dist/core/tools/index.d.ts.map +1 -0
  56. package/dist/core/tools/index.js +13 -0
  57. package/dist/core/tools/index.js.map +1 -0
  58. package/dist/core/tools/list-shop-items.d.ts +8 -0
  59. package/dist/core/tools/list-shop-items.d.ts.map +1 -0
  60. package/dist/core/tools/list-shop-items.js +17 -0
  61. package/dist/core/tools/list-shop-items.js.map +1 -0
  62. package/dist/core/tools/update-game.d.ts +11 -0
  63. package/dist/core/tools/update-game.d.ts.map +1 -0
  64. package/dist/core/tools/update-game.js +22 -0
  65. package/dist/core/tools/update-game.js.map +1 -0
  66. package/dist/core/tools/update-shop-item.d.ts +15 -0
  67. package/dist/core/tools/update-shop-item.d.ts.map +1 -0
  68. package/dist/core/tools/update-shop-item.js +24 -0
  69. package/dist/core/tools/update-shop-item.js.map +1 -0
  70. package/dist/core/tools/upload-game-asset.d.ts +8 -0
  71. package/dist/core/tools/upload-game-asset.d.ts.map +1 -0
  72. package/dist/core/tools/upload-game-asset.js +43 -0
  73. package/dist/core/tools/upload-game-asset.js.map +1 -0
  74. package/dist/core/tools/upload-version.d.ts +8 -0
  75. package/dist/core/tools/upload-version.d.ts.map +1 -0
  76. package/dist/core/tools/upload-version.js +20 -0
  77. package/dist/core/tools/upload-version.js.map +1 -0
  78. package/dist/core/tools/validate-game.d.ts +6 -0
  79. package/dist/core/tools/validate-game.d.ts.map +1 -0
  80. package/dist/core/tools/validate-game.js +41 -0
  81. package/dist/core/tools/validate-game.js.map +1 -0
  82. package/dist/core/tools.test.d.ts +2 -0
  83. package/dist/core/tools.test.d.ts.map +1 -0
  84. package/dist/core/tools.test.js +825 -0
  85. package/dist/core/tools.test.js.map +1 -0
  86. package/dist/generated/server-api.d.ts +3673 -0
  87. package/dist/generated/server-api.d.ts.map +1 -0
  88. package/dist/generated/server-api.js +2 -0
  89. package/dist/generated/server-api.js.map +1 -0
  90. package/dist/index.d.ts +3 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +365 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/server/create-server.d.ts +12 -0
  95. package/dist/server/create-server.d.ts.map +1 -0
  96. package/dist/server/create-server.js +29 -0
  97. package/dist/server/create-server.js.map +1 -0
  98. package/dist/server/create-server.test.d.ts +2 -0
  99. package/dist/server/create-server.test.d.ts.map +1 -0
  100. package/dist/server/create-server.test.js +37 -0
  101. package/dist/server/create-server.test.js.map +1 -0
  102. package/dist/server/index.d.ts +3 -0
  103. package/dist/server/index.d.ts.map +1 -0
  104. package/dist/server/index.js +8 -0
  105. package/dist/server/index.js.map +1 -0
  106. package/dist/server/lib/config.d.ts +2 -0
  107. package/dist/server/lib/config.d.ts.map +1 -0
  108. package/dist/server/lib/config.js +2 -0
  109. package/dist/server/lib/config.js.map +1 -0
  110. package/dist/server/resources/skills.d.ts +3 -0
  111. package/dist/server/resources/skills.d.ts.map +1 -0
  112. package/dist/server/resources/skills.js +60 -0
  113. package/dist/server/resources/skills.js.map +1 -0
  114. package/dist/server/resources/skills.test.d.ts +2 -0
  115. package/dist/server/resources/skills.test.d.ts.map +1 -0
  116. package/dist/server/resources/skills.test.js +44 -0
  117. package/dist/server/resources/skills.test.js.map +1 -0
  118. package/dist/server/tools/register.d.ts +3 -0
  119. package/dist/server/tools/register.d.ts.map +1 -0
  120. package/dist/server/tools/register.js +26 -0
  121. package/dist/server/tools/register.js.map +1 -0
  122. package/dist/server/tools/register.test.d.ts +2 -0
  123. package/dist/server/tools/register.test.d.ts.map +1 -0
  124. package/dist/server/tools/register.test.js +85 -0
  125. package/dist/server/tools/register.test.js.map +1 -0
  126. package/dist/types.d.ts +73 -0
  127. package/dist/types.d.ts.map +1 -0
  128. package/dist/types.js +31 -0
  129. package/dist/types.js.map +1 -0
  130. package/package.json +38 -0
  131. package/skills/SKILL.md +82 -0
  132. package/skills/actions/open-game.md +18 -0
  133. package/skills/workflows/add-image-to-game.md +121 -0
  134. package/skills/workflows/add-sprite-to-game.md +127 -0
  135. package/skills/workflows/game-creation.md +124 -0
  136. package/skills/workflows/implement-multiplayer.md +355 -0
  137. package/skills/workflows/integrate-save-game.md +135 -0
  138. package/skills/workflows/manage-shop-items.md +246 -0
  139. package/skills/workflows/upload-game.md +74 -0
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it, mock } from 'bun:test';
2
+ import { SERVER_INSTRUCTIONS, createServer } from './create-server.js';
3
+ class MockMcpServer {
4
+ definition;
5
+ options;
6
+ static instances = [];
7
+ constructor(definition, options) {
8
+ this.definition = definition;
9
+ this.options = options;
10
+ MockMcpServer.instances.push(this);
11
+ }
12
+ }
13
+ const registerAllTools = mock(() => { });
14
+ const registerSkillResources = mock(() => { });
15
+ describe('createServer()', () => {
16
+ it('builds the MCP server with the expected metadata and registrations', () => {
17
+ MockMcpServer.instances = [];
18
+ const server = createServer({
19
+ McpServerClass: MockMcpServer,
20
+ registerTools: registerAllTools,
21
+ registerResources: registerSkillResources,
22
+ });
23
+ expect(MockMcpServer.instances).toHaveLength(1);
24
+ const createdServer = server;
25
+ expect(createdServer).toBe(MockMcpServer.instances[0]);
26
+ expect(createdServer.definition).toEqual({
27
+ name: 'remix-mcp',
28
+ version: '0.1.0',
29
+ });
30
+ expect(createdServer.options).toEqual({
31
+ instructions: SERVER_INSTRUCTIONS,
32
+ });
33
+ expect(registerAllTools).toHaveBeenCalledWith(server);
34
+ expect(registerSkillResources).toHaveBeenCalledWith(server);
35
+ });
36
+ });
37
+ //# sourceMappingURL=create-server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-server.test.js","sourceRoot":"","sources":["../../src/server/create-server.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtE,MAAM,aAAa;IACjB,UAAU,CAAS;IACnB,OAAO,CAAS;IAChB,MAAM,CAAC,SAAS,GAAoB,EAAE,CAAA;IAEtC,YAAY,UAAmB,EAAE,OAAgB;QAC/C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;;AAGH,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;AACvC,MAAM,sBAAsB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;AAE7C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,aAAa,CAAC,SAAS,GAAG,EAAE,CAAA;QAE5B,MAAM,MAAM,GAAG,YAAY,CAAC;YAC1B,cAAc,EAAE,aAAsB;YACtC,aAAa,EAAE,gBAAgB;YAC/B,iBAAiB,EAAE,sBAAsB;SAC1C,CAAC,CAAA;QAEF,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,aAAa,GAAG,MAAkC,CAAA;QAExD,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;QACtD,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;YACvC,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,OAAO;SACjB,CAAC,CAAA;QACF,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACpC,YAAY,EAAE,mBAAmB;SAClC,CAAC,CAAA;QACF,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAA;QACrD,MAAM,CAAC,sBAAsB,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createServer } from './create-server.js';
4
+ const server = createServer();
5
+ const transport = new StdioServerTransport();
6
+ // biome-ignore lint/suspicious/noExplicitAny: upstream SDK has duplicate installs with incompatible Transport types
7
+ await server.connect(transport);
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;AAC7B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;AAC5C,oHAAoH;AACpH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAgB,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { getConfig, type RemixConfig } from '../../core/config.js';
2
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/server/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { getConfig } from '../../core/config.js';
2
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerSkillResources(server: McpServer, loadFile?: (filename: string) => string): void;
3
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/server/resources/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAyCxE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,QAAQ,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAsB,QAwCvD"}
@@ -0,0 +1,60 @@
1
+ import { loadSkillFile } from '../../core/skills.js';
2
+ const SKILL_WORKFLOWS = {
3
+ 'game-creation': {
4
+ file: 'workflows/game-creation.md',
5
+ description: 'Create a new HTML5 game from scratch with Remix scaffolding.',
6
+ },
7
+ 'upload-game': {
8
+ file: 'workflows/upload-game.md',
9
+ description: 'Package and upload a finished game to the Remix platform.',
10
+ },
11
+ 'implement-multiplayer': {
12
+ file: 'workflows/implement-multiplayer.md',
13
+ description: 'Integrate turn-based multiplayer using the Remix SDK.',
14
+ },
15
+ 'integrate-save-game': {
16
+ file: 'workflows/integrate-save-game.md',
17
+ description: 'Add save/load game state using the Remix SDK.',
18
+ },
19
+ 'add-image-to-game': {
20
+ file: 'workflows/add-image-to-game.md',
21
+ description: 'Add and manage image assets in a Remix game project.',
22
+ },
23
+ 'manage-shop-items': {
24
+ file: 'workflows/manage-shop-items.md',
25
+ description: 'Create, list, update, delete, and integrate shop items.',
26
+ },
27
+ 'add-sprite-to-game': {
28
+ file: 'workflows/add-sprite-to-game.md',
29
+ description: 'Generate and integrate animated sprite sheets in a Remix game.',
30
+ },
31
+ };
32
+ const SKILL_ACTIONS = {
33
+ 'open-game': {
34
+ file: 'actions/open-game.md',
35
+ description: 'Open a game in the Remix Studio for preview and editing.',
36
+ },
37
+ };
38
+ export function registerSkillResources(server, loadFile = loadSkillFile) {
39
+ // Static resource: master skill overview
40
+ server.registerResource('skills-overview', 'skills://overview', {
41
+ description: 'Master overview of all available agent skills for the Remix Platform. ' +
42
+ 'Read this first to understand what workflows are available.',
43
+ mimeType: 'text/markdown',
44
+ }, async (uri) => ({
45
+ contents: [{ uri: uri.href, text: loadFile('SKILL.md') }],
46
+ }));
47
+ // Individual workflow skill resources
48
+ for (const [key, { file, description }] of Object.entries(SKILL_WORKFLOWS)) {
49
+ server.registerResource(`skill-${key}`, `skills://${key}`, { description, mimeType: 'text/markdown' }, async (uri) => ({
50
+ contents: [{ uri: uri.href, text: loadFile(file) }],
51
+ }));
52
+ }
53
+ // Individual action skill resources
54
+ for (const [key, { file, description }] of Object.entries(SKILL_ACTIONS)) {
55
+ server.registerResource(`skill-${key}`, `skills://${key}`, { description, mimeType: 'text/markdown' }, async (uri) => ({
56
+ contents: [{ uri: uri.href, text: loadFile(file) }],
57
+ }));
58
+ }
59
+ }
60
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/server/resources/skills.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,MAAM,eAAe,GAA0D;IAC7E,eAAe,EAAE;QACf,IAAI,EAAE,4BAA4B;QAClC,WAAW,EAAE,8DAA8D;KAC5E;IACD,aAAa,EAAE;QACb,IAAI,EAAE,0BAA0B;QAChC,WAAW,EAAE,2DAA2D;KACzE;IACD,uBAAuB,EAAE;QACvB,IAAI,EAAE,oCAAoC;QAC1C,WAAW,EAAE,uDAAuD;KACrE;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,kCAAkC;QACxC,WAAW,EAAE,+CAA+C;KAC7D;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,gCAAgC;QACtC,WAAW,EAAE,sDAAsD;KACpE;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,gCAAgC;QACtC,WAAW,EAAE,yDAAyD;KACvE;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,iCAAiC;QACvC,WAAW,EAAE,gEAAgE;KAC9E;CACF,CAAA;AAED,MAAM,aAAa,GAA0D;IAC3E,WAAW,EAAE;QACX,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,0DAA0D;KACxE;CACF,CAAA;AAED,MAAM,UAAU,sBAAsB,CACpC,MAAiB,EACjB,WAAyC,aAAa;IAEtD,yCAAyC;IACzC,MAAM,CAAC,gBAAgB,CACrB,iBAAiB,EACjB,mBAAmB,EACnB;QACE,WAAW,EACT,wEAAwE;YACxE,6DAA6D;QAC/D,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;KAC1D,CAAC,CACH,CAAA;IAED,sCAAsC;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3E,MAAM,CAAC,gBAAgB,CACrB,SAAS,GAAG,EAAE,EACd,YAAY,GAAG,EAAE,EACjB,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,EAC1C,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;SACpD,CAAC,CACH,CAAA;IACH,CAAC;IAED,oCAAoC;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,gBAAgB,CACrB,SAAS,GAAG,EAAE,EACd,YAAY,GAAG,EAAE,EACjB,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,EAC1C,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;SACpD,CAAC,CACH,CAAA;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=skills.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.test.d.ts","sourceRoot":"","sources":["../../../src/server/resources/skills.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it, mock } from 'bun:test';
2
+ const loadSkillFile = mock((filename) => `contents:${filename}`);
3
+ const { registerSkillResources } = await import('./skills.js');
4
+ describe('registerSkillResources()', () => {
5
+ it('registers overview, workflows, and actions with expected loaders', async () => {
6
+ const registrations = [];
7
+ const server = {
8
+ registerResource: mock((name, uri, metadata, handler) => {
9
+ registrations.push({ name, uri, metadata, handler });
10
+ }),
11
+ };
12
+ registerSkillResources(server, loadSkillFile);
13
+ expect(server.registerResource).toHaveBeenCalledTimes(9);
14
+ expect(registrations.map((registration) => registration.uri)).toEqual([
15
+ 'skills://overview',
16
+ 'skills://game-creation',
17
+ 'skills://upload-game',
18
+ 'skills://implement-multiplayer',
19
+ 'skills://integrate-save-game',
20
+ 'skills://add-image-to-game',
21
+ 'skills://manage-shop-items',
22
+ 'skills://add-sprite-to-game',
23
+ 'skills://open-game',
24
+ ]);
25
+ const overviewRegistration = registrations[0];
26
+ const openGameRegistration = registrations[8];
27
+ expect(overviewRegistration).toBeDefined();
28
+ expect(openGameRegistration).toBeDefined();
29
+ if (!overviewRegistration || !openGameRegistration) {
30
+ throw new Error('Missing expected skill registrations');
31
+ }
32
+ const overview = await overviewRegistration.handler(new URL('skills://overview'));
33
+ const openGame = await openGameRegistration.handler(new URL('skills://open-game'));
34
+ expect(loadSkillFile).toHaveBeenCalledWith('SKILL.md');
35
+ expect(loadSkillFile).toHaveBeenCalledWith('actions/open-game.md');
36
+ expect(overview).toEqual({
37
+ contents: [{ uri: 'skills://overview', text: 'contents:SKILL.md' }],
38
+ });
39
+ expect(openGame).toEqual({
40
+ contents: [{ uri: 'skills://open-game', text: 'contents:actions/open-game.md' }],
41
+ });
42
+ });
43
+ });
44
+ //# sourceMappingURL=skills.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.test.js","sourceRoot":"","sources":["../../../src/server/resources/skills.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAErD,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,QAAgB,EAAE,EAAE,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAA;AACxE,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;AAE9D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,aAAa,GAKd,EAAE,CAAA;QAEP,MAAM,MAAM,GAAG;YACb,gBAAgB,EAAE,IAAI,CACpB,CACE,IAAY,EACZ,GAAW,EACX,QAAiC,EACjC,OAAuC,EACvC,EAAE;gBACF,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;YACtD,CAAC,CACF;SACF,CAAA;QAED,sBAAsB,CAAC,MAAe,EAAE,aAAa,CAAC,CAAA;QAEtD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QACxD,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YACpE,mBAAmB;YACnB,wBAAwB;YACxB,sBAAsB;YACtB,gCAAgC;YAChC,8BAA8B;YAC9B,4BAA4B;YAC5B,4BAA4B;YAC5B,6BAA6B;YAC7B,oBAAoB;SACrB,CAAC,CAAA;QAEF,MAAM,oBAAoB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,oBAAoB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAA;QAC1C,MAAM,CAAC,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAA;QAC1C,IAAI,CAAC,oBAAoB,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACzD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAA;QACjF,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAA;QAElF,MAAM,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAA;QACtD,MAAM,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;QAClE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACvB,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;SACpE,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACvB,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,+BAA+B,EAAE,CAAC;SACjF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerAllTools(server: McpServer, toolDefs?: import("../../core/tool-defs.js").ToolDefinition<import("zod").ZodObject<any, import("zod/v4/core").$strip>>[]): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../src/server/tools/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,iHAAY,QAyBvE"}
@@ -0,0 +1,26 @@
1
+ import { TOOL_DEFS } from '../../core/tool-defs.js';
2
+ export function registerAllTools(server, toolDefs = TOOL_DEFS) {
3
+ for (const def of toolDefs) {
4
+ server.registerTool(def.name, {
5
+ title: def.title,
6
+ description: def.description,
7
+ inputSchema: def.inputSchema.shape,
8
+ },
9
+ // biome-ignore lint/suspicious/noExplicitAny: MCP callback input is schema-validated at runtime
10
+ async (input) => {
11
+ try {
12
+ const result = await def.execute(input);
13
+ return {
14
+ content: [{ type: 'text', text: def.formatResult(result) }],
15
+ };
16
+ }
17
+ catch (err) {
18
+ return {
19
+ content: [{ type: 'text', text: err.message }],
20
+ isError: true,
21
+ };
22
+ }
23
+ });
24
+ }
25
+ }
26
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../../src/server/tools/register.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEnD,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,QAAQ,GAAG,SAAS;IACtE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,CAAC,YAAY,CACjB,GAAG,CAAC,IAAI,EACR;YACE,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC,KAAK;SACnC;QACD,gGAAgG;QAChG,KAAK,EAAE,KAAU,EAAE,EAAE;YACnB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;gBACvC,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;iBACrE,CAAA;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC;oBAClE,OAAO,EAAE,IAAI;iBACd,CAAA;YACH,CAAC;QACH,CAAC,CACF,CAAA;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=register.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.test.d.ts","sourceRoot":"","sources":["../../../src/server/tools/register.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { describe, expect, it, mock } from 'bun:test';
2
+ const executeOk = mock(async () => ({ gameId: 'game-1' }));
3
+ const executeError = mock(async () => {
4
+ throw new Error('boom');
5
+ });
6
+ const formatOk = mock(() => 'formatted success');
7
+ const formatUnused = mock(() => 'formatted error');
8
+ const { registerAllTools } = await import('./register.js');
9
+ const toolDefs = [
10
+ {
11
+ name: 'createGame',
12
+ title: 'Create Game',
13
+ description: 'Creates a game',
14
+ inputSchema: {
15
+ shape: {
16
+ name: { type: 'string' },
17
+ },
18
+ },
19
+ execute: executeOk,
20
+ formatResult: formatOk,
21
+ },
22
+ {
23
+ name: 'uploadVersion',
24
+ title: 'Upload Version',
25
+ description: 'Uploads a version',
26
+ inputSchema: {
27
+ shape: {
28
+ gameId: { type: 'string' },
29
+ },
30
+ },
31
+ execute: executeError,
32
+ formatResult: formatUnused,
33
+ },
34
+ ];
35
+ describe('registerAllTools()', () => {
36
+ it('registers each tool and formats successful executions', async () => {
37
+ const registrations = [];
38
+ const server = {
39
+ registerTool: mock((name, metadata, handler) => {
40
+ registrations.push({ name, metadata, handler });
41
+ }),
42
+ };
43
+ registerAllTools(server, toolDefs);
44
+ expect(server.registerTool).toHaveBeenCalledTimes(2);
45
+ expect(registrations[0]?.name).toBe('createGame');
46
+ expect(registrations[0]?.metadata).toEqual({
47
+ title: 'Create Game',
48
+ description: 'Creates a game',
49
+ inputSchema: {
50
+ name: { type: 'string' },
51
+ },
52
+ });
53
+ const registration = registrations[0];
54
+ expect(registration).toBeDefined();
55
+ if (!registration)
56
+ throw new Error('Missing createGame registration');
57
+ const result = await registration.handler({ name: 'Test Game' });
58
+ expect(executeOk).toHaveBeenCalledWith({ name: 'Test Game' });
59
+ expect(formatOk).toHaveBeenCalledWith({ gameId: 'game-1' });
60
+ expect(result).toEqual({
61
+ content: [{ type: 'text', text: 'formatted success' }],
62
+ });
63
+ });
64
+ it('returns MCP error payloads when tool execution throws', async () => {
65
+ const registrations = [];
66
+ const server = {
67
+ registerTool: mock((_name, _metadata, handler) => {
68
+ registrations.push({ handler });
69
+ }),
70
+ };
71
+ registerAllTools(server, toolDefs);
72
+ const registration = registrations[1];
73
+ expect(registration).toBeDefined();
74
+ if (!registration)
75
+ throw new Error('Missing uploadVersion registration');
76
+ const result = await registration.handler({ gameId: 'game-1' });
77
+ expect(executeError).toHaveBeenCalledWith({ gameId: 'game-1' });
78
+ expect(formatUnused).not.toHaveBeenCalled();
79
+ expect(result).toEqual({
80
+ content: [{ type: 'text', text: 'boom' }],
81
+ isError: true,
82
+ });
83
+ });
84
+ });
85
+ //# sourceMappingURL=register.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.test.js","sourceRoot":"","sources":["../../../src/server/tools/register.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Configuration schema for Remix MCP
4
+ */
5
+ export declare const ConfigSchema: z.ZodObject<{
6
+ gameId: z.ZodOptional<z.ZodString>;
7
+ apiKey: z.ZodOptional<z.ZodString>;
8
+ apiUrl: z.ZodOptional<z.ZodString>;
9
+ }, z.core.$strip>;
10
+ export type Config = z.infer<typeof ConfigSchema>;
11
+ /**
12
+ * Schema for set_config tool input
13
+ */
14
+ export declare const SetConfigInputSchema: z.ZodObject<{
15
+ gameId: z.ZodOptional<z.ZodString>;
16
+ apiKey: z.ZodOptional<z.ZodString>;
17
+ apiUrl: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strip>;
19
+ export type SetConfigInput = z.infer<typeof SetConfigInputSchema>;
20
+ /**
21
+ * Schema for upload_version tool input
22
+ */
23
+ export declare const UploadVersionInputSchema: z.ZodObject<{
24
+ codePath: z.ZodString;
25
+ }, z.core.$strip>;
26
+ export type UploadVersionInput = z.infer<typeof UploadVersionInputSchema>;
27
+ /**
28
+ * Game object returned from API
29
+ */
30
+ export interface Game {
31
+ id: string;
32
+ name: string;
33
+ createdAt: string;
34
+ updatedAt: string;
35
+ }
36
+ /**
37
+ * API response when listing games
38
+ */
39
+ export interface ListGamesResponse {
40
+ success: boolean;
41
+ games?: Game[];
42
+ error?: string;
43
+ }
44
+ /**
45
+ * Schema for create_game tool input
46
+ */
47
+ export declare const CreateGameInputSchema: z.ZodObject<{
48
+ name: z.ZodString;
49
+ codePath: z.ZodString;
50
+ }, z.core.$strip>;
51
+ export type CreateGameInput = z.infer<typeof CreateGameInputSchema>;
52
+ /**
53
+ * API response when creating a game
54
+ */
55
+ export interface CreateGameResponse {
56
+ success: boolean;
57
+ game?: Game;
58
+ error?: string;
59
+ }
60
+ /**
61
+ * API response when creating a game version
62
+ */
63
+ export interface UploadVersionResponse {
64
+ success: boolean;
65
+ version?: {
66
+ id: string;
67
+ title: string;
68
+ createdAt: Date;
69
+ };
70
+ error?: string;
71
+ details?: unknown;
72
+ }
73
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;GAEG;AACH,eAAO,MAAM,YAAY;;;;iBAIvB,CAAA;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AAEjD;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;iBAI/B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE;;GAEG;AACH,eAAO,MAAM,wBAAwB;;iBAEnC,CAAA;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAEzE;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;iBAGhC,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE;QACR,EAAE,EAAE,MAAM,CAAA;QACV,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,IAAI,CAAA;KAChB,CAAA;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Configuration schema for Remix MCP
4
+ */
5
+ export const ConfigSchema = z.object({
6
+ gameId: z.string().optional(),
7
+ apiKey: z.string().optional(),
8
+ apiUrl: z.string().url().optional(),
9
+ });
10
+ /**
11
+ * Schema for set_config tool input
12
+ */
13
+ export const SetConfigInputSchema = z.object({
14
+ gameId: z.string().optional().describe('The game ID to upload versions for'),
15
+ apiKey: z.string().optional().describe('API key for authentication'),
16
+ apiUrl: z.string().url().optional().describe('API URL (defaults to https://remix.gg)'),
17
+ });
18
+ /**
19
+ * Schema for upload_version tool input
20
+ */
21
+ export const UploadVersionInputSchema = z.object({
22
+ codePath: z.string().describe('Path to the game code file to upload'),
23
+ });
24
+ /**
25
+ * Schema for create_game tool input
26
+ */
27
+ export const CreateGameInputSchema = z.object({
28
+ name: z.string().describe('Name of the game to create'),
29
+ codePath: z.string().describe('Path to the game code file'),
30
+ });
31
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAA;AAIF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IAC5E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;IACpE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;CACvF,CAAC,CAAA;AAIF;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;CACtE,CAAC,CAAA;AAuBF;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;IACvD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;CAC5D,CAAC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@remix-gg/mcp",
3
+ "version": "0.4.3",
4
+ "description": "MCP server + skills for building remix HTML games",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "files": ["dist", "skills", "README.md"],
10
+ "exports": {
11
+ ".": "./dist/client-helpers/index.js",
12
+ "./core": "./dist/core/index.js",
13
+ "./server": "./dist/server/index.js",
14
+ "./skills": "./skills/"
15
+ },
16
+ "bin": {
17
+ "remix-mcp": "./dist/server/index.js"
18
+ },
19
+ "scripts": {
20
+ "generate:server-api-sdk": "bun run scripts/generate-server-api-sdk.ts",
21
+ "prepublishOnly": "tsc",
22
+ "build": "tsc",
23
+ "test": "bun test src",
24
+ "dev": "tsx --watch src/server/index.ts",
25
+ "start": "node dist/server/index.js"
26
+ },
27
+ "dependencies": {
28
+ "@modelcontextprotocol/sdk": "1.26.0",
29
+ "openapi-fetch": "0.17.0",
30
+ "zod": "^4.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^22.10.5",
34
+ "openapi-typescript": "7.13.0",
35
+ "tsx": "^4.21.0",
36
+ "typescript": "5.8.3"
37
+ }
38
+ }
@@ -0,0 +1,82 @@
1
+ # Remix Platform — Agent Skills
2
+
3
+ You are an agent working with the Remix Platform. This document provides
4
+ the master overview of how to build, validate, and publish HTML games.
5
+
6
+ ## Authentication
7
+
8
+ This server requires a Remix API key via the `REMIX_API_KEY` environment variable.
9
+ Keys can be obtained from https://remix.gg.
10
+
11
+ ## Game Settings
12
+
13
+ Game IDs are persisted in a `.remix-settings.json` file in the project root.
14
+
15
+ **CRITICAL:** Before calling `createGame` or any tool that requires `gameId`
16
+ or `versionId`, you MUST read this file to check for existing values. If it
17
+ contains `gameId` and `versionId`, **do NOT call `createGame`** — use the
18
+ existing IDs. Calling `createGame` when IDs already exist creates a duplicate.
19
+
20
+ After calling `createGame` (only when no IDs exist), write the returned IDs
21
+ (and game name) back to `.remix-settings.json` so they persist across sessions.
22
+
23
+ ```json
24
+ {
25
+ "gameId": "uuid-here",
26
+ "versionId": "uuid-here",
27
+ "name": "My Game"
28
+ }
29
+ ```
30
+
31
+ ## Available Tools
32
+
33
+ - **validateGame** — Validates an HTML game file for common issues (missing
34
+ DOCTYPE, viewport, inline handlers, infinite loops). Takes a `filePath` — do
35
+ NOT read the game file yourself. Call this before uploading.
36
+ - **createGame** — Creates a new game on the Remix platform. Takes a `name`,
37
+ returns the game ID and version ID needed for subsequent tool calls.
38
+ - **uploadVersion** — Uploads an HTML game file to an existing game version.
39
+ Requires `gameId` and `versionId` from createGame. Takes a `filePath` — do
40
+ NOT read the game file yourself.
41
+ - **generateImage** — Generates an AI image from a text prompt. Returns base64
42
+ image data as an MCP image content block.
43
+ - **uploadGameAsset** — Uploads a local file as a game asset. Takes a
44
+ `filePath`, returns JSON with the hosted asset URL.
45
+ - **listShopItems** — Lists the current shop items for a game.
46
+ - **createShopItem** — Creates a Bits shop item for a game.
47
+ Use this for consumables, one-time unlocks, and tier unlock items. When
48
+ `iconUrl` is omitted for `CONSUMABLE` or `ONE_TIME`, the tool auto-generates
49
+ and uploads a shop icon.
50
+ - **updateShopItem** — Updates an existing shop item.
51
+ - **deleteShopItem** — Deletes or deactivates an existing shop item.
52
+ - **updateGame** — Updates game settings (name, multiplayer flag). Takes a
53
+ `gameId` and optional `name` and `isMultiplayer` fields.
54
+
55
+ ## Available Workflows
56
+
57
+ - **game-creation** — How to create a new game from scratch
58
+ - **upload-game** — How to validate and upload a game to the Remix platform
59
+ - **integrate-save-game** — How to persist and restore game state across sessions
60
+ - **add-image-to-game** — How to generate, upload, and integrate images into a game
61
+ - **manage-shop-items** — How to create, list, update, delete, and consume shop items
62
+ - **implement-multiplayer** — How to integrate turn-based multiplayer into a game
63
+
64
+ ## Available Actions
65
+
66
+ - **open-game** — Open a game in the Remix Studio for preview
67
+
68
+ ## How to Use
69
+
70
+ **Always load the appropriate workflow or action skill before taking action.**
71
+ Each skill contains the exact steps, tool calls, and validation checks needed.
72
+ Do not act on general knowledge — follow the skill instructions.
73
+
74
+ 1. Identify which workflow or action matches the task (see "Available Workflows"
75
+ and "Available Actions" above).
76
+ 2. Load it via the `getSkill` resource (e.g. `skills://upload-game`,
77
+ `skills://open-game`).
78
+ 3. Follow its step-by-step instructions exactly.
79
+
80
+ If you're unsure which skill to use, start with **game-creation** for
81
+ building games, **upload-game** for deploying them, or **open-game** for
82
+ previewing them in the Remix Studio.
@@ -0,0 +1,18 @@
1
+ # Open Game in Remix Studio
2
+
3
+ Open the current game in the Remix Studio for preview and editing.
4
+
5
+ ## Steps
6
+
7
+ 1. **Read game settings** from `.remix-settings.json` in the project root.
8
+ Extract `gameId` and `versionId`. If either is missing, tell the user
9
+ they need to create/upload a game first.
10
+
11
+ 2. **Construct the Studio URL:**
12
+ ```
13
+ https://remix.gg/games/{gameId}/v/{versionId}
14
+ ```
15
+
16
+ 3. **Open in the user's default browser:**
17
+ - macOS: `open <url>`
18
+ - Linux: `xdg-open <url>`