@epic-web/workshop-mcp 6.38.0 → 6.40.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.
package/dist/esm/index.js CHANGED
@@ -24,7 +24,9 @@ const server = new McpServer({
24
24
  capabilities: {
25
25
  tools: {},
26
26
  },
27
- }, {
27
+ },
28
+ // TODO: add some common workflows to the instructions
29
+ {
28
30
  instructions: `
29
31
  This is intended to be used within a workshop using the Epic Workshop App
30
32
  (@epic-web/workshop-app) to help learners in the process of completing the
@@ -32,6 +34,8 @@ workshop exercises and understanding the learning outcomes.
32
34
 
33
35
  The user's work in progress is in the \`playground\` directory. Any changes they
34
36
  ask you to make should be in this directory.
37
+
38
+ Most of the time you should use the \`get_what_is_next\` tool to get the next step the user needs to complete.
35
39
  `.trim(),
36
40
  });
37
41
  // Wrap with Sentry if enabled
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE1E,4BAA4B;AAC5B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;AAEpB,sDAAsD;AACtD,IAAI,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC;QACX,GAAG,EAAE,GAAG,CAAC,UAAU;QACnB,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa;QACrE,gBAAgB,EAAE,GAAG;KACrB,CAAC,CAAA;AACH,CAAC;AAED,yBAAyB;AACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC3B;IACC,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE;QACb,KAAK,EAAE,EAAE;KACT;CACD,EACD;IACC,YAAY,EAAE;;;;;;;GAOb,CAAC,IAAI,EAAE;CACR,CACD,CAAA;AAED,8BAA8B;AAC9B,MAAM,eAAe,GACpB,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,UAAU;IAC1C,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC;IACxC,CAAC,CAAC,MAAM,CAAA;AAEV,SAAS,CAAC,eAAe,CAAC,CAAA;AAC1B,iBAAiB,CAAC,eAAe,CAAC,CAAA;AAClC,aAAa,CAAC,eAAe,CAAC,CAAA;AAC9B,WAAW,CAAC,eAAe,CAAC,CAAA;AAC5B,eAAe,CAAC,eAAe,CAAC,CAAA;AAEhC,KAAK,UAAU,IAAI;IAClB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;IAC5C,MAAM,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACxC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;AACtD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAC,CAAA","sourcesContent":["#!/usr/bin/env node\n\nimport { getEnv } from '@epic-web/workshop-utils/init-env'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport * as Sentry from '@sentry/node'\nimport { initPrompts } from './prompts.js'\nimport { initResources } from './resources.js'\nimport { initPromptTools, initResourceTools, initTools } from './tools.js'\n\n// Get environment variables\nconst env = getEnv()\n\n// Initialize Sentry if published and DSN is available\nif (env.EPICSHOP_IS_PUBLISHED && env.SENTRY_DSN) {\n\tSentry.init({\n\t\tdsn: env.SENTRY_DSN,\n\t\tsendDefaultPii: true,\n\t\tenvironment: env.EPICSHOP_IS_PUBLISHED ? 'production' : 'development',\n\t\ttracesSampleRate: 1.0,\n\t})\n}\n\n// Create server instance\nconst server = new McpServer(\n\t{\n\t\tname: 'epicshop',\n\t\tversion: '1.0.0',\n\t\tcapabilities: {\n\t\t\ttools: {},\n\t\t},\n\t},\n\t{\n\t\tinstructions: `\nThis is intended to be used within a workshop using the Epic Workshop App\n(@epic-web/workshop-app) to help learners in the process of completing the\nworkshop exercises and understanding the learning outcomes.\n\nThe user's work in progress is in the \\`playground\\` directory. Any changes they\nask you to make should be in this directory.\n\t\t`.trim(),\n\t},\n)\n\n// Wrap with Sentry if enabled\nconst monitoredServer =\n\tenv.EPICSHOP_IS_PUBLISHED && env.SENTRY_DSN\n\t\t? Sentry.wrapMcpServerWithSentry(server)\n\t\t: server\n\ninitTools(monitoredServer)\ninitResourceTools(monitoredServer)\ninitResources(monitoredServer)\ninitPrompts(monitoredServer)\ninitPromptTools(monitoredServer)\n\nasync function main() {\n\tconst transport = new StdioServerTransport()\n\tawait monitoredServer.connect(transport)\n\tconsole.error('epicshop MCP Server running on stdio')\n}\n\nmain().catch((error) => {\n\tconsole.error('Fatal error in main():', error)\n\tprocess.exit(1)\n})\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE1E,4BAA4B;AAC5B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;AAEpB,sDAAsD;AACtD,IAAI,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC;QACX,GAAG,EAAE,GAAG,CAAC,UAAU;QACnB,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa;QACrE,gBAAgB,EAAE,GAAG;KACrB,CAAC,CAAA;AACH,CAAC;AAED,yBAAyB;AACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC3B;IACC,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE;QACb,KAAK,EAAE,EAAE;KACT;CACD;AACD,sDAAsD;AACtD;IACC,YAAY,EAAE;;;;;;;;;GASb,CAAC,IAAI,EAAE;CACR,CACD,CAAA;AAED,8BAA8B;AAC9B,MAAM,eAAe,GACpB,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,UAAU;IAC1C,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC;IACxC,CAAC,CAAC,MAAM,CAAA;AAEV,SAAS,CAAC,eAAe,CAAC,CAAA;AAC1B,iBAAiB,CAAC,eAAe,CAAC,CAAA;AAClC,aAAa,CAAC,eAAe,CAAC,CAAA;AAC9B,WAAW,CAAC,eAAe,CAAC,CAAA;AAC5B,eAAe,CAAC,eAAe,CAAC,CAAA;AAEhC,KAAK,UAAU,IAAI;IAClB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;IAC5C,MAAM,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACxC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;AACtD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAC,CAAA","sourcesContent":["#!/usr/bin/env node\n\nimport { getEnv } from '@epic-web/workshop-utils/init-env'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport * as Sentry from '@sentry/node'\nimport { initPrompts } from './prompts.js'\nimport { initResources } from './resources.js'\nimport { initPromptTools, initResourceTools, initTools } from './tools.js'\n\n// Get environment variables\nconst env = getEnv()\n\n// Initialize Sentry if published and DSN is available\nif (env.EPICSHOP_IS_PUBLISHED && env.SENTRY_DSN) {\n\tSentry.init({\n\t\tdsn: env.SENTRY_DSN,\n\t\tsendDefaultPii: true,\n\t\tenvironment: env.EPICSHOP_IS_PUBLISHED ? 'production' : 'development',\n\t\ttracesSampleRate: 1.0,\n\t})\n}\n\n// Create server instance\nconst server = new McpServer(\n\t{\n\t\tname: 'epicshop',\n\t\tversion: '1.0.0',\n\t\tcapabilities: {\n\t\t\ttools: {},\n\t\t},\n\t},\n\t// TODO: add some common workflows to the instructions\n\t{\n\t\tinstructions: `\nThis is intended to be used within a workshop using the Epic Workshop App\n(@epic-web/workshop-app) to help learners in the process of completing the\nworkshop exercises and understanding the learning outcomes.\n\nThe user's work in progress is in the \\`playground\\` directory. Any changes they\nask you to make should be in this directory.\n\nMost of the time you should use the \\`get_what_is_next\\` tool to get the next step the user needs to complete.\n\t\t`.trim(),\n\t},\n)\n\n// Wrap with Sentry if enabled\nconst monitoredServer =\n\tenv.EPICSHOP_IS_PUBLISHED && env.SENTRY_DSN\n\t\t? Sentry.wrapMcpServerWithSentry(server)\n\t\t: server\n\ninitTools(monitoredServer)\ninitResourceTools(monitoredServer)\ninitResources(monitoredServer)\ninitPrompts(monitoredServer)\ninitPromptTools(monitoredServer)\n\nasync function main() {\n\tconst transport = new StdioServerTransport()\n\tawait monitoredServer.connect(transport)\n\tconsole.error('epicshop MCP Server running on stdio')\n}\n\nmain().catch((error) => {\n\tconsole.error('Fatal error in main():', error)\n\tprocess.exit(1)\n})\n"]}
@@ -60,6 +60,23 @@ export declare const exerciseContextResource: {
60
60
  exerciseNumber: z.ZodOptional<z.ZodNumber>;
61
61
  };
62
62
  };
63
+ declare const getExerciseStepContextInputSchema: {
64
+ workshopDirectory: z.ZodString;
65
+ exerciseNumber: z.ZodNumber;
66
+ stepNumber: z.ZodNumber;
67
+ };
68
+ declare function getExerciseStepContextResource({ workshopDirectory, exerciseNumber, stepNumber, }: InputSchemaType<typeof getExerciseStepContextInputSchema>): Promise<ReadResourceResult['contents'][number]>;
69
+ export declare const exerciseStepContextResource: {
70
+ name: string;
71
+ description: string;
72
+ uriTemplate: ResourceTemplate;
73
+ getResource: typeof getExerciseStepContextResource;
74
+ inputSchema: {
75
+ workshopDirectory: z.ZodString;
76
+ exerciseNumber: z.ZodNumber;
77
+ stepNumber: z.ZodNumber;
78
+ };
79
+ };
63
80
  declare const diffBetweenAppsInputSchema: {
64
81
  workshopDirectory: z.ZodString;
65
82
  app1: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/resources.ts"],"names":[],"mappings":"AAoBA,OAAO,EACN,KAAK,SAAS,EACd,gBAAgB,EAChB,MAAM,yCAAyC,CAAA;AAChD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AAC5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAEN,KAAK,eAAe,EAGpB,MAAM,YAAY,CAAA;AAEnB,eAAO,MAAM,6BAA6B;;CAEzC,CAAA;AAED,wBAAsB,kBAAkB,CAAC,EACxC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,6BAA6B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAqBrC,KAAK,CAAC,GAAG,CAAC;GA0D5B;AAOD,wBAAsB,0BAA0B,CAAC,EAChD,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,6BAA6B,CAAC,GAAG,OAAO,CACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAQA;AAED,eAAO,MAAM,uBAAuB;;;;;;;;CAMnC,CAAA;AA4LD,iBAAe,0BAA0B,CAAC,EACzC,iBAAiB,EACjB,cAAc,GACd,EAAE;IACF,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAalD;AAED,eAAO,MAAM,uBAAuB;;;;;;;;;CAMnC,CAAA;AAED,QAAA,MAAM,0BAA0B;;;;CAI/B,CAAA;AA4CD,iBAAe,0BAA0B,CAAC,EACzC,iBAAiB,EACjB,IAAI,EACJ,IAAI,GACJ,EAAE,eAAe,CAAC,OAAO,0BAA0B,CAAC,GAAG,OAAO,CAC9D,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAYA;AAOD,eAAO,MAAM,uBAAuB;;;;;;;;;;CAMnC,CAAA;AAED,QAAA,MAAM,sCAAsC;;CAE3C,CAAA;AAoCD,iBAAe,mCAAmC,CAAC,EAClD,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,sCAAsC,CAAC,GAAG,OAAO,CAC1E,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAUA;AAED,eAAO,MAAM,gCAAgC;;;;;;;;CAM5C,CAAA;AAED,QAAA,MAAM,sBAAsB;;CAE3B,CAAA;AAOD,iBAAe,mBAAmB,CAAC,EAClC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,sBAAsB,CAAC;;;;GAShD;AAED,eAAO,MAAM,gBAAgB;;;;;;;;CAM5B,CAAA;AAED,QAAA,MAAM,wBAAwB;;CAE7B,CAAA;AAOD,iBAAe,qBAAqB,CAAC,EACpC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,wBAAwB,CAAC;;;;GASlD;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAM9B,CAAA;AAED,QAAA,MAAM,uBAAuB;;CAE5B,CAAA;AAOD,iBAAe,uBAAuB,CAAC,EACtC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,uBAAuB,CAAC;;;;GASjD;AAED,eAAO,MAAM,oBAAoB;;;;;;;;CAMhC,CAAA;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,QAgJ9C"}
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/resources.ts"],"names":[],"mappings":"AAoBA,OAAO,EACN,KAAK,SAAS,EACd,gBAAgB,EAChB,MAAM,yCAAyC,CAAA;AAChD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AAC5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAEN,KAAK,eAAe,EAIpB,MAAM,YAAY,CAAA;AAEnB,eAAO,MAAM,6BAA6B;;CAEzC,CAAA;AAED,wBAAsB,kBAAkB,CAAC,EACxC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,6BAA6B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAmBrC,KAAK,CAAC,GAAG,CAAC;GA0D5B;AAOD,wBAAsB,0BAA0B,CAAC,EAChD,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,6BAA6B,CAAC,GAAG,OAAO,CACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAQA;AAED,eAAO,MAAM,uBAAuB;;;;;;;;CAMnC,CAAA;AAgJD,iBAAe,0BAA0B,CAAC,EACzC,iBAAiB,EACjB,cAAc,GACd,EAAE;IACF,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAalD;AAED,eAAO,MAAM,uBAAuB;;;;;;;;;CAMnC,CAAA;AAiFD,QAAA,MAAM,iCAAiC;;;;CAQtC,CAAA;AAkGD,iBAAe,8BAA8B,CAAC,EAC7C,iBAAiB,EACjB,cAAc,EACd,UAAU,GACV,EAAE,eAAe,CAAC,OAAO,iCAAiC,CAAC,GAAG,OAAO,CACrE,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAeA;AAED,eAAO,MAAM,2BAA2B;;;;;;;;;;CAMvC,CAAA;AAED,QAAA,MAAM,0BAA0B;;;;CAI/B,CAAA;AA4CD,iBAAe,0BAA0B,CAAC,EACzC,iBAAiB,EACjB,IAAI,EACJ,IAAI,GACJ,EAAE,eAAe,CAAC,OAAO,0BAA0B,CAAC,GAAG,OAAO,CAC9D,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAYA;AAOD,eAAO,MAAM,uBAAuB;;;;;;;;;;CAMnC,CAAA;AAED,QAAA,MAAM,sCAAsC;;CAE3C,CAAA;AAoCD,iBAAe,mCAAmC,CAAC,EAClD,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,sCAAsC,CAAC,GAAG,OAAO,CAC1E,kBAAkB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CACtC,CAUA;AAED,eAAO,MAAM,gCAAgC;;;;;;;;CAM5C,CAAA;AAED,QAAA,MAAM,sBAAsB;;CAE3B,CAAA;AAOD,iBAAe,mBAAmB,CAAC,EAClC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,sBAAsB,CAAC;;;;GAShD;AAED,eAAO,MAAM,gBAAgB;;;;;;;;CAM5B,CAAA;AAED,QAAA,MAAM,wBAAwB;;CAE7B,CAAA;AAOD,iBAAe,qBAAqB,CAAC,EACpC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,wBAAwB,CAAC;;;;GASlD;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAM9B,CAAA;AAED,QAAA,MAAM,uBAAuB;;CAE5B,CAAA;AAOD,iBAAe,uBAAuB,CAAC,EACtC,iBAAiB,GACjB,EAAE,eAAe,CAAC,OAAO,uBAAuB,CAAC;;;;GASjD;AAED,eAAO,MAAM,oBAAoB;;;;;;;;CAMhC,CAAA;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,QAiM9C"}
@@ -5,25 +5,23 @@ import { getAuthInfo } from '@epic-web/workshop-utils/db.server';
5
5
  import { getEpicVideoInfos, userHasAccessToWorkshop, getUserInfo, getProgress, } from '@epic-web/workshop-utils/epic-api.server';
6
6
  import { ResourceTemplate, } from '@modelcontextprotocol/sdk/server/mcp.js';
7
7
  import { z } from 'zod';
8
- import { handleWorkshopDirectory, safeReadFile, workshopDirectoryInputSchema, } from './utils.js';
8
+ import { handleWorkshopDirectory, readInWorkshop, safeReadFile, workshopDirectoryInputSchema, } from './utils.js';
9
9
  export const getWorkshopContextInputSchema = {
10
10
  workshopDirectory: workshopDirectoryInputSchema,
11
11
  };
12
12
  export async function getWorkshopContext({ workshopDirectory, }) {
13
- const workshopRoot = await handleWorkshopDirectory(workshopDirectory);
14
- const inWorkshop = (...d) => path.join(workshopRoot, ...d);
15
- const readInWorkshop = (...d) => safeReadFile(inWorkshop(...d));
13
+ await handleWorkshopDirectory(workshopDirectory);
16
14
  const progress = await getProgress();
17
15
  const output = {
18
16
  meta: {
19
17
  'README.md': await readInWorkshop('README.md'),
20
18
  config: JSON.parse((await readInWorkshop('package.json')) || '{}').epicshop,
21
19
  instructions: {
22
- content: await readInWorkshop('exercise', 'README.mdx'),
20
+ content: await readInWorkshop('exercises', 'README.mdx'),
23
21
  progress: progress.find((p) => p.type === 'instructions'),
24
22
  },
25
23
  finishedInstructions: {
26
- content: await readInWorkshop('exercise', 'FINISHED.mdx'),
24
+ content: await readInWorkshop('exercises', 'FINISHED.mdx'),
27
25
  progress: progress.find((p) => p.type === 'finished'),
28
26
  },
29
27
  },
@@ -98,15 +96,8 @@ const getExerciseContextInputSchema = {
98
96
  .describe(`The exercise number to get the context for (defaults to the exercise number the playground is currently set to)`),
99
97
  };
100
98
  async function getExerciseContext({ workshopDirectory, exerciseNumber, }) {
101
- await handleWorkshopDirectory(workshopDirectory);
102
- const userHasAccess = await userHasAccessToWorkshop();
103
- const authInfo = await getAuthInfo();
104
- const progress = await getProgress();
99
+ const { userHasAccess, authInfo, progress, numbers } = await getCommonContextData(workshopDirectory);
105
100
  let stepNumber = 1;
106
- const playgroundApp = await getPlaygroundApp();
107
- const numbers = playgroundApp
108
- ? extractNumbersAndTypeFromAppNameOrPath(playgroundApp.appName)
109
- : null;
110
101
  const isCurrentExercise = exerciseNumber === undefined ||
111
102
  exerciseNumber === Number(numbers?.exerciseNumber);
112
103
  if (exerciseNumber === undefined) {
@@ -122,63 +113,6 @@ async function getExerciseContext({ workshopDirectory, exerciseNumber, }) {
122
113
  ...exercise.steps.flatMap((s) => s.solution?.epicVideoEmbeds ?? []),
123
114
  ...(exercise.finishedEpicVideoEmbeds ?? []),
124
115
  ]);
125
- function getTranscripts(embeds) {
126
- if (!embeds)
127
- return [];
128
- if (!userHasAccess && embeds.length) {
129
- return [
130
- {
131
- message: `User must upgrade before they can get access to ${embeds.length} transcript${embeds.length === 1 ? '' : 's'}.`,
132
- },
133
- ];
134
- }
135
- return embeds.map((embed) => {
136
- const info = videoInfos[embed];
137
- if (info) {
138
- if (info.status === 'error') {
139
- if (info.type === 'region-restricted') {
140
- return {
141
- embed,
142
- status: 'error',
143
- type: info.type,
144
- requestedCountry: info.requestCountry,
145
- restrictedCountry: info.restrictedCountry,
146
- };
147
- }
148
- else {
149
- return {
150
- embed,
151
- status: 'error',
152
- type: info.type,
153
- statusCode: info.statusCode,
154
- statusText: info.statusText,
155
- };
156
- }
157
- }
158
- else {
159
- return {
160
- embed,
161
- status: 'success',
162
- transcript: info.transcript,
163
- };
164
- }
165
- }
166
- else {
167
- return {
168
- embed,
169
- status: 'error',
170
- type: 'not-found',
171
- message: 'No transcript found',
172
- };
173
- }
174
- });
175
- }
176
- async function getFileContent(filePath) {
177
- return {
178
- path: filePath,
179
- content: (await safeReadFile(filePath)) ?? 'None found',
180
- };
181
- }
182
116
  const context = {
183
117
  currentContext: {
184
118
  user: {
@@ -197,12 +131,12 @@ async function getExerciseContext({ workshopDirectory, exerciseNumber, }) {
197
131
  number: exerciseNumber,
198
132
  intro: {
199
133
  content: await getFileContent(path.join(exercise.fullPath, 'README.mdx')),
200
- transcripts: getTranscripts(exercise.instructionsEpicVideoEmbeds),
134
+ transcripts: getTranscripts(exercise.instructionsEpicVideoEmbeds, videoInfos, userHasAccess),
201
135
  progress: progress.find((p) => p.type === 'instructions' && p.exerciseNumber === exerciseNumber),
202
136
  },
203
137
  outro: {
204
138
  content: await getFileContent(path.join(exercise.fullPath, 'FINISHED.mdx')),
205
- transcripts: getTranscripts(exercise.finishedEpicVideoEmbeds),
139
+ transcripts: getTranscripts(exercise.finishedEpicVideoEmbeds, videoInfos, userHasAccess),
206
140
  progress: progress.find((p) => p.type === 'finished' && p.exerciseNumber === exerciseNumber),
207
141
  },
208
142
  },
@@ -217,13 +151,13 @@ async function getExerciseContext({ workshopDirectory, exerciseNumber, }) {
217
151
  content: app.problem
218
152
  ? await getFileContent(path.join(app.problem.fullPath, 'README.mdx'))
219
153
  : 'No problem found',
220
- transcripts: getTranscripts(app.problem?.epicVideoEmbeds),
154
+ transcripts: getTranscripts(app.problem?.epicVideoEmbeds, videoInfos, userHasAccess),
221
155
  },
222
156
  solution: {
223
157
  content: app.solution
224
158
  ? await getFileContent(path.join(app.solution.fullPath, 'README.mdx'))
225
159
  : 'No solution found',
226
- transcripts: getTranscripts(app.solution?.epicVideoEmbeds),
160
+ transcripts: getTranscripts(app.solution?.epicVideoEmbeds, videoInfos, userHasAccess),
227
161
  },
228
162
  })))
229
163
  : [],
@@ -261,6 +195,171 @@ export const exerciseContextResource = {
261
195
  getResource: getExerciseContextResource,
262
196
  inputSchema: getExerciseContextInputSchema,
263
197
  };
198
+ // Common helper functions extracted from getExerciseContext
199
+ async function getCommonContextData(workshopDirectory) {
200
+ await handleWorkshopDirectory(workshopDirectory);
201
+ const userHasAccess = await userHasAccessToWorkshop();
202
+ const authInfo = await getAuthInfo();
203
+ const progress = await getProgress();
204
+ const playgroundApp = await getPlaygroundApp();
205
+ const numbers = playgroundApp
206
+ ? extractNumbersAndTypeFromAppNameOrPath(playgroundApp.appName)
207
+ : null;
208
+ return {
209
+ userHasAccess,
210
+ authInfo,
211
+ progress,
212
+ playgroundApp,
213
+ numbers,
214
+ };
215
+ }
216
+ function getTranscripts(embeds, videoInfos, userHasAccess) {
217
+ if (!embeds)
218
+ return [];
219
+ if (!userHasAccess && embeds.length) {
220
+ return [
221
+ {
222
+ message: `User must upgrade before they can get access to ${embeds.length} transcript${embeds.length === 1 ? '' : 's'}.`,
223
+ },
224
+ ];
225
+ }
226
+ return embeds.map((embed) => {
227
+ const info = videoInfos[embed];
228
+ if (info) {
229
+ if (info.status === 'error') {
230
+ if (info.type === 'region-restricted') {
231
+ return {
232
+ embed,
233
+ status: 'error',
234
+ type: info.type,
235
+ requestedCountry: info.requestCountry,
236
+ restrictedCountry: info.restrictedCountry,
237
+ };
238
+ }
239
+ else {
240
+ return {
241
+ embed,
242
+ status: 'error',
243
+ type: info.type,
244
+ statusCode: info.statusCode,
245
+ statusText: info.statusText,
246
+ };
247
+ }
248
+ }
249
+ else {
250
+ return {
251
+ embed,
252
+ status: 'success',
253
+ transcript: info.transcript,
254
+ };
255
+ }
256
+ }
257
+ else {
258
+ return {
259
+ embed,
260
+ status: 'error',
261
+ type: 'not-found',
262
+ message: 'No transcript found',
263
+ };
264
+ }
265
+ });
266
+ }
267
+ async function getFileContent(filePath) {
268
+ return {
269
+ path: filePath,
270
+ content: (await safeReadFile(filePath)) ?? 'None found',
271
+ };
272
+ }
273
+ const getExerciseStepContextInputSchema = {
274
+ workshopDirectory: workshopDirectoryInputSchema,
275
+ exerciseNumber: z.coerce
276
+ .number()
277
+ .describe('The exercise number to get the context for'),
278
+ stepNumber: z.coerce
279
+ .number()
280
+ .describe('The step number to get the context for'),
281
+ };
282
+ async function getExerciseStepContext({ workshopDirectory, exerciseNumber, stepNumber, }) {
283
+ const { userHasAccess, authInfo, progress, numbers } = await getCommonContextData(workshopDirectory);
284
+ const isCurrentExercise = exerciseNumber === Number(numbers?.exerciseNumber) &&
285
+ stepNumber === Number(numbers?.stepNumber);
286
+ const exercise = await getExercise(exerciseNumber);
287
+ invariant(exercise, `No exercise found for exercise number ${exerciseNumber}`);
288
+ const step = exercise.steps.find((s) => s.stepNumber === stepNumber);
289
+ invariant(step, `No step found for exercise ${exerciseNumber}, step ${stepNumber}`);
290
+ const videoInfos = await getEpicVideoInfos([
291
+ ...(step.problem?.epicVideoEmbeds ?? []),
292
+ ...(step.solution?.epicVideoEmbeds ?? []),
293
+ ]);
294
+ const context = {
295
+ currentContext: {
296
+ user: {
297
+ hasAccess: userHasAccess,
298
+ isAuthenticated: Boolean(authInfo),
299
+ email: authInfo?.email,
300
+ },
301
+ playground: isCurrentExercise
302
+ ? {
303
+ exerciseNumber,
304
+ stepNumber,
305
+ }
306
+ : 'currently set to a different exercise step',
307
+ },
308
+ exerciseInfo: {
309
+ number: exerciseNumber,
310
+ title: exercise.title,
311
+ },
312
+ stepInfo: {
313
+ number: stepNumber,
314
+ isCurrent: isCurrentExercise,
315
+ progress: progress.find((p) => p.type === 'step' &&
316
+ p.exerciseNumber === exerciseNumber &&
317
+ p.stepNumber === stepNumber),
318
+ title: step.problem?.title ?? step.solution?.title ?? null,
319
+ },
320
+ problem: {
321
+ content: step.problem
322
+ ? await getFileContent(path.join(step.problem.fullPath, 'README.mdx'))
323
+ : 'No problem found',
324
+ transcripts: getTranscripts(step.problem?.epicVideoEmbeds, videoInfos, userHasAccess),
325
+ },
326
+ solution: {
327
+ content: step.solution
328
+ ? await getFileContent(path.join(step.solution.fullPath, 'README.mdx'))
329
+ : 'No solution found',
330
+ transcripts: getTranscripts(step.solution?.epicVideoEmbeds, videoInfos, userHasAccess),
331
+ },
332
+ notes: [],
333
+ };
334
+ if (isCurrentExercise) {
335
+ context.notes.push(`This is the current step the user is working on. The playground is set to exercise ${exerciseNumber}, step ${stepNumber}.`);
336
+ }
337
+ return context;
338
+ }
339
+ const exerciseStepContextUriTemplate = new ResourceTemplate('epicshop://{workshopDirectory}/exercise/{exerciseNumber}/{stepNumber}', { list: undefined });
340
+ async function getExerciseStepContextResource({ workshopDirectory, exerciseNumber, stepNumber, }) {
341
+ const context = await getExerciseStepContext({
342
+ workshopDirectory,
343
+ exerciseNumber,
344
+ stepNumber,
345
+ });
346
+ return {
347
+ uri: exerciseStepContextUriTemplate.uriTemplate.expand({
348
+ workshopDirectory,
349
+ exerciseNumber: String(exerciseNumber),
350
+ stepNumber: String(stepNumber),
351
+ }),
352
+ mimeType: 'application/json',
353
+ text: JSON.stringify(context),
354
+ };
355
+ }
356
+ export const exerciseStepContextResource = {
357
+ name: 'exercise_step_context',
358
+ description: 'The context of a specific exercise step',
359
+ uriTemplate: exerciseStepContextUriTemplate,
360
+ getResource: getExerciseStepContextResource,
361
+ inputSchema: getExerciseStepContextInputSchema,
362
+ };
264
363
  const diffBetweenAppsInputSchema = {
265
364
  workshopDirectory: workshopDirectoryInputSchema,
266
365
  app1: z.string().describe('The ID of the first app'),
@@ -433,6 +532,27 @@ export function initResources(server) {
433
532
  ],
434
533
  };
435
534
  });
535
+ server.registerResource(exerciseStepContextResource.name, exerciseStepContextResource.uriTemplate, { description: exerciseStepContextResource.description }, async (_uri, { workshopDirectory, exerciseNumber: providedExerciseNumber, stepNumber: providedStepNumber, }) => {
536
+ invariant(typeof workshopDirectory === 'string', 'A single workshopDirectory is required');
537
+ invariant(typeof providedExerciseNumber === 'string', 'A single exerciseNumber is required');
538
+ invariant(typeof providedStepNumber === 'string', 'A single stepNumber is required');
539
+ const exerciseNumber = Number(providedExerciseNumber);
540
+ const stepNumber = Number(providedStepNumber);
541
+ invariant(!isNaN(exerciseNumber), 'exerciseNumber must be a number');
542
+ invariant(!isNaN(stepNumber), 'stepNumber must be a number');
543
+ invariant(exerciseNumber >= 0, 'exerciseNumber must be greater than or equal to 0');
544
+ invariant(stepNumber >= 0, 'stepNumber must be greater than or equal to 0');
545
+ workshopDirectory = await handleWorkshopDirectory(workshopDirectory);
546
+ return {
547
+ contents: [
548
+ await exerciseStepContextResource.getResource({
549
+ workshopDirectory,
550
+ exerciseNumber,
551
+ stepNumber,
552
+ }),
553
+ ],
554
+ };
555
+ });
436
556
  server.registerResource(diffBetweenAppsResource.name, diffBetweenAppsResource.uriTemplate, { description: diffBetweenAppsResource.description }, async (_uri, { workshopDirectory, app1, app2 }) => {
437
557
  invariant(typeof workshopDirectory === 'string', 'A single workshopDirectory is required');
438
558
  invariant(typeof app1 === 'string', 'A single app1 is required');
@@ -1 +1 @@
1
- {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/resources.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path'\nimport { invariant } from '@epic-web/invariant'\nimport {\n\textractNumbersAndTypeFromAppNameOrPath,\n\tfindSolutionDir,\n\tgetApps,\n\tgetExercise,\n\tgetExercises,\n\tgetFullPathFromAppName,\n\tgetPlaygroundApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getAuthInfo } from '@epic-web/workshop-utils/db.server'\nimport {\n\tgetEpicVideoInfos,\n\tuserHasAccessToWorkshop,\n\tgetUserInfo,\n\tgetProgress,\n} from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\ttype McpServer,\n\tResourceTemplate,\n} from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { type ReadResourceResult } from '@modelcontextprotocol/sdk/types.js'\nimport { z } from 'zod'\nimport {\n\thandleWorkshopDirectory,\n\ttype InputSchemaType,\n\tsafeReadFile,\n\tworkshopDirectoryInputSchema,\n} from './utils.js'\n\nexport const getWorkshopContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nexport async function getWorkshopContext({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getWorkshopContextInputSchema>) {\n\tconst workshopRoot = await handleWorkshopDirectory(workshopDirectory)\n\tconst inWorkshop = (...d: Array<string>) => path.join(workshopRoot, ...d)\n\tconst readInWorkshop = (...d: Array<string>) => safeReadFile(inWorkshop(...d))\n\tconst progress = await getProgress()\n\n\tconst output = {\n\t\tmeta: {\n\t\t\t'README.md': await readInWorkshop('README.md'),\n\t\t\tconfig: (\n\t\t\t\tJSON.parse((await readInWorkshop('package.json')) || '{}') as any\n\t\t\t).epicshop,\n\t\t\tinstructions: {\n\t\t\t\tcontent: await readInWorkshop('exercise', 'README.mdx'),\n\t\t\t\tprogress: progress.find((p) => p.type === 'instructions'),\n\t\t\t},\n\t\t\tfinishedInstructions: {\n\t\t\t\tcontent: await readInWorkshop('exercise', 'FINISHED.mdx'),\n\t\t\t\tprogress: progress.find((p) => p.type === 'finished'),\n\t\t\t},\n\t\t},\n\t\texercises: [] as Array<any>,\n\t}\n\n\tconst exercises = await getExercises()\n\tfor (const exercise of exercises) {\n\t\tconst exerciseInfo = {\n\t\t\tfullPath: exercise.fullPath,\n\t\t\texerciseNumber: exercise.exerciseNumber,\n\t\t\ttitle: exercise.title,\n\t\t\tinstructions: {\n\t\t\t\tcontent: await safeReadFile(path.join(exercise.fullPath, 'README.mdx')),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'instructions' &&\n\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\tfinishedInstructions: {\n\t\t\t\tcontent: await safeReadFile(\n\t\t\t\t\tpath.join(exercise.fullPath, 'FINISHED.mdx'),\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'finished' &&\n\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\tsteps: exercise.steps.map((step) => {\n\t\t\t\treturn {\n\t\t\t\t\tstepNumber: step.stepNumber,\n\t\t\t\t\tprogress: progress.find(\n\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber &&\n\t\t\t\t\t\t\tp.stepNumber === step.stepNumber,\n\t\t\t\t\t),\n\t\t\t\t\ttitle: step.problem?.title ?? step.solution?.title ?? null,\n\t\t\t\t\tproblem: step.problem\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfullPath: step.problem.fullPath,\n\t\t\t\t\t\t\t\ttestConfig: step.problem.test,\n\t\t\t\t\t\t\t\tdevConfig: step.problem.dev,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: 'No problem app',\n\t\t\t\t\tsolution: step.solution\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfullPath: step.solution.fullPath,\n\t\t\t\t\t\t\t\ttestConfig: step.solution.test,\n\t\t\t\t\t\t\t\tdevConfig: step.solution.dev,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: 'No solution app',\n\t\t\t\t}\n\t\t\t}),\n\t\t}\n\t\toutput.exercises.push(exerciseInfo)\n\t}\n\n\treturn output\n}\n\nconst workshopContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/workshop-context',\n\t{ list: undefined },\n)\n\nexport async function getWorkshopContextResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getWorkshopContextInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: workshopContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(await getWorkshopContext({ workshopDirectory })),\n\t}\n}\n\nexport const workshopContextResource = {\n\tname: 'workshop_context',\n\tdescription: 'The context of the workshop',\n\turiTemplate: workshopContextUriTemplate,\n\tgetResource: getWorkshopContextResource,\n\tinputSchema: getWorkshopContextInputSchema,\n}\n\nconst getExerciseContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\texerciseNumber: z.coerce\n\t\t.number()\n\t\t.optional()\n\t\t.describe(\n\t\t\t`The exercise number to get the context for (defaults to the exercise number the playground is currently set to)`,\n\t\t),\n}\n\nasync function getExerciseContext({\n\tworkshopDirectory,\n\texerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: number\n}) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\tconst userHasAccess = await userHasAccessToWorkshop()\n\tconst authInfo = await getAuthInfo()\n\tconst progress = await getProgress()\n\tlet stepNumber = 1\n\tconst playgroundApp = await getPlaygroundApp()\n\tconst numbers = playgroundApp\n\t\t? extractNumbersAndTypeFromAppNameOrPath(playgroundApp.appName)\n\t\t: null\n\tconst isCurrentExercise =\n\t\texerciseNumber === undefined ||\n\t\texerciseNumber === Number(numbers?.exerciseNumber)\n\tif (exerciseNumber === undefined) {\n\t\tinvariant(numbers, 'No numbers found in playground app name')\n\t\texerciseNumber = Number(numbers.exerciseNumber)\n\t\tstepNumber = Number(numbers.stepNumber)\n\t}\n\tconst exercise = await getExercise(exerciseNumber)\n\tinvariant(exercise, `No exercise found for exercise number ${exerciseNumber}`)\n\n\tconst videoInfos = await getEpicVideoInfos([\n\t\t...(exercise.instructionsEpicVideoEmbeds ?? []),\n\t\t...exercise.steps.flatMap((s) => s.problem?.epicVideoEmbeds ?? []),\n\t\t...exercise.steps.flatMap((s) => s.solution?.epicVideoEmbeds ?? []),\n\t\t...(exercise.finishedEpicVideoEmbeds ?? []),\n\t])\n\n\tfunction getTranscripts(embeds?: Array<string>) {\n\t\tif (!embeds) return []\n\t\tif (!userHasAccess && embeds.length) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tmessage: `User must upgrade before they can get access to ${embeds.length} transcript${embeds.length === 1 ? '' : 's'}.`,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\t\treturn embeds.map((embed) => {\n\t\t\tconst info = videoInfos[embed]\n\t\t\tif (info) {\n\t\t\t\tif (info.status === 'error') {\n\t\t\t\t\tif (info.type === 'region-restricted') {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tembed,\n\t\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\t\ttype: info.type,\n\t\t\t\t\t\t\trequestedCountry: info.requestCountry,\n\t\t\t\t\t\t\trestrictedCountry: info.restrictedCountry,\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tembed,\n\t\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\t\ttype: info.type,\n\t\t\t\t\t\t\tstatusCode: info.statusCode,\n\t\t\t\t\t\t\tstatusText: info.statusText,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tembed,\n\t\t\t\t\t\tstatus: 'success',\n\t\t\t\t\t\ttranscript: info.transcript,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tembed,\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\ttype: 'not-found',\n\t\t\t\t\tmessage: 'No transcript found',\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tasync function getFileContent(filePath: string) {\n\t\treturn {\n\t\t\tpath: filePath,\n\t\t\tcontent: (await safeReadFile(filePath)) ?? 'None found',\n\t\t}\n\t}\n\n\tconst context = {\n\t\tcurrentContext: {\n\t\t\tuser: {\n\t\t\t\thasAccess: userHasAccess,\n\t\t\t\tisAuthenticated: Boolean(authInfo),\n\t\t\t\temail: authInfo?.email,\n\t\t\t},\n\t\t\tplayground: isCurrentExercise\n\t\t\t\t? {\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}\n\t\t\t\t: 'currently set to a different exercise',\n\t\t},\n\t\texerciseInfo: {\n\t\t\tnumber: exerciseNumber,\n\t\t\tintro: {\n\t\t\t\tcontent: await getFileContent(\n\t\t\t\t\tpath.join(exercise.fullPath, 'README.mdx'),\n\t\t\t\t),\n\t\t\t\ttranscripts: getTranscripts(exercise.instructionsEpicVideoEmbeds),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'instructions' && p.exerciseNumber === exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\toutro: {\n\t\t\t\tcontent: await getFileContent(\n\t\t\t\t\tpath.join(exercise.fullPath, 'FINISHED.mdx'),\n\t\t\t\t),\n\t\t\t\ttranscripts: getTranscripts(exercise.finishedEpicVideoEmbeds),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) => p.type === 'finished' && p.exerciseNumber === exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t\tsteps: exercise.steps\n\t\t\t? await Promise.all(\n\t\t\t\t\texercise.steps.map(async (app) => ({\n\t\t\t\t\t\tnumber: app.stepNumber,\n\t\t\t\t\t\tisCurrent: isCurrentExercise && app.stepNumber === stepNumber,\n\t\t\t\t\t\tprogress: progress.find(\n\t\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\t\t\t\tp.exerciseNumber === exerciseNumber &&\n\t\t\t\t\t\t\t\tp.stepNumber === app.stepNumber,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tproblem: {\n\t\t\t\t\t\t\tcontent: app.problem\n\t\t\t\t\t\t\t\t? await getFileContent(\n\t\t\t\t\t\t\t\t\t\tpath.join(app.problem.fullPath, 'README.mdx'),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: 'No problem found',\n\t\t\t\t\t\t\ttranscripts: getTranscripts(app.problem?.epicVideoEmbeds),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsolution: {\n\t\t\t\t\t\t\tcontent: app.solution\n\t\t\t\t\t\t\t\t? await getFileContent(\n\t\t\t\t\t\t\t\t\t\tpath.join(app.solution.fullPath, 'README.mdx'),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: 'No solution found',\n\t\t\t\t\t\t\ttranscripts: getTranscripts(app.solution?.epicVideoEmbeds),\n\t\t\t\t\t\t},\n\t\t\t\t\t})),\n\t\t\t\t)\n\t\t\t: [],\n\t\tnotes: [] as Array<string>,\n\t}\n\n\tif (exercise.steps) {\n\t\tif (isCurrentExercise) {\n\t\t\tcontext.notes.push(\n\t\t\t\t`Reminder, the current step is ${stepNumber} of ${exercise.steps.length + 1}. The most relevant information will be in the context above within the current step.`,\n\t\t\t)\n\t\t}\n\t} else {\n\t\tcontext.notes.push('Unusually, this exercise has no steps.')\n\t}\n\n\treturn context\n}\n\nconst exerciseContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise/{exerciseNumber}',\n\t{ list: undefined },\n)\n\nasync function getExerciseContextResource({\n\tworkshopDirectory,\n\texerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: number\n}): Promise<ReadResourceResult['contents'][number]> {\n\tconst context = await getExerciseContext({\n\t\tworkshopDirectory,\n\t\texerciseNumber,\n\t})\n\treturn {\n\t\turi: exerciseContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\texerciseNumber: String(context.exerciseInfo.number),\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(context),\n\t}\n}\n\nexport const exerciseContextResource = {\n\tname: 'exercise_context',\n\tdescription: 'The context of the exercise',\n\turiTemplate: exerciseContextUriTemplate,\n\tgetResource: getExerciseContextResource,\n\tinputSchema: getExerciseContextInputSchema,\n}\n\nconst diffBetweenAppsInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\tapp1: z.string().describe('The ID of the first app'),\n\tapp2: z.string().describe('The ID of the second app'),\n}\n\nasync function getDiffBetweenApps({\n\tworkshopDirectory,\n\tapp1,\n\tapp2,\n}: InputSchemaType<typeof diffBetweenAppsInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\n\tconst { getDiffOutputWithRelativePaths } = await import(\n\t\t'@epic-web/workshop-utils/diff.server'\n\t)\n\n\tconst app1Name = extractNumbersAndTypeFromAppNameOrPath(app1)\n\tconst app2Name = extractNumbersAndTypeFromAppNameOrPath(app2)\n\n\tconst apps = await getApps()\n\tconst app1App = apps\n\t\t.filter(isExerciseStepApp)\n\t\t.find(\n\t\t\t(a) =>\n\t\t\t\ta.exerciseNumber === Number(app1Name?.exerciseNumber) &&\n\t\t\t\ta.stepNumber === Number(app1Name?.stepNumber) &&\n\t\t\t\ta.type === app1Name?.type,\n\t\t)\n\tconst app2App = apps\n\t\t.filter(isExerciseStepApp)\n\t\t.find(\n\t\t\t(a) =>\n\t\t\t\ta.exerciseNumber === Number(app2Name?.exerciseNumber) &&\n\t\t\t\ta.stepNumber === Number(app2Name?.stepNumber) &&\n\t\t\t\ta.type === app2Name?.type,\n\t\t)\n\n\tinvariant(app1App, `No app found for ${app1}`)\n\tinvariant(app2App, `No app found for ${app2}`)\n\n\tconst diffCode = await getDiffOutputWithRelativePaths(app1App, app2App)\n\n\tif (!diffCode) return 'No changes'\n\n\treturn diffCode\n}\n\nasync function getDiffBetweenAppsResource({\n\tworkshopDirectory,\n\tapp1,\n\tapp2,\n}: InputSchemaType<typeof diffBetweenAppsInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: diffBetweenAppsUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\tapp1,\n\t\t\tapp2,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(\n\t\t\tawait getDiffBetweenApps({ workshopDirectory, app1, app2 }),\n\t\t),\n\t}\n}\n\nconst diffBetweenAppsUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/diff-between-apps/{app1}__vs___{app2}',\n\t{ list: undefined },\n)\n\nexport const diffBetweenAppsResource = {\n\tname: 'diff_between_apps',\n\tdescription: 'The diff between two apps',\n\turiTemplate: diffBetweenAppsUriTemplate,\n\tgetResource: getDiffBetweenAppsResource,\n\tinputSchema: diffBetweenAppsInputSchema,\n}\n\nconst getExerciseStepProgressDiffInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nasync function getExerciseStepProgressDiff({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getExerciseStepProgressDiffInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\n\tconst { getDiffOutputWithRelativePaths } = await import(\n\t\t'@epic-web/workshop-utils/diff.server'\n\t)\n\n\tconst apps = await getApps()\n\tconst playgroundApp = apps.find(isPlaygroundApp)\n\n\tinvariant(playgroundApp, 'No playground app found')\n\n\tconst baseApp = playgroundApp\n\tconst solutionDir = await findSolutionDir({\n\t\tfullPath: await getFullPathFromAppName(playgroundApp.appName),\n\t})\n\tconst headApp = apps.find((a) => a.fullPath === solutionDir)\n\n\tinvariant(headApp, 'No playground solution app found')\n\n\tconst diffCode = await getDiffOutputWithRelativePaths(baseApp, headApp)\n\n\tif (!diffCode) return 'No changes'\n\n\treturn diffCode\n}\n\nconst exerciseStepProgressDiffUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise-step-progress-diff',\n\t{ list: undefined },\n)\n\nasync function getExerciseStepProgressDiffResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getExerciseStepProgressDiffInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: exerciseStepProgressDiffUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(\n\t\t\tawait getExerciseStepProgressDiff({ workshopDirectory }),\n\t\t),\n\t}\n}\n\nexport const exerciseStepProgressDiffResource = {\n\tname: 'exercise_step_progress_diff',\n\tdescription: 'The diff between the current exercise step and the solution',\n\turiTemplate: exerciseStepProgressDiffUriTemplate,\n\tgetResource: getExerciseStepProgressDiffResource,\n\tinputSchema: getExerciseStepProgressDiffInputSchema,\n}\n\nconst getUserInfoInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userInfoUri = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/info',\n\t{ list: undefined },\n)\n\nasync function getUserInfoResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getUserInfoInputSchema>) {\n\tconst userInfo = await getUserInfo()\n\treturn {\n\t\turi: userInfoUri.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(userInfo),\n\t}\n}\n\nexport const userInfoResource = {\n\tname: 'user_info',\n\tdescription: 'Information about the current user',\n\turiTemplate: userInfoUri,\n\tgetResource: getUserInfoResource,\n\tinputSchema: getUserInfoInputSchema,\n}\n\nconst getUserAccessInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userAccessUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/access',\n\t{ list: undefined },\n)\n\nasync function getUserAccessResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getUserAccessInputSchema>) {\n\tconst userHasAccess = await userHasAccessToWorkshop()\n\treturn {\n\t\turi: userAccessUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify({ userHasAccess }),\n\t}\n}\n\nexport const userAccessResource = {\n\tname: 'user_access',\n\tdescription: 'Whether the current user has access to the workshop',\n\turiTemplate: userAccessUriTemplate,\n\tgetResource: getUserAccessResource,\n\tinputSchema: getUserAccessInputSchema,\n}\n\nconst userProgressInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userProgressUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/progress',\n\t{ list: undefined },\n)\n\nasync function getUserProgressResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof userProgressInputSchema>) {\n\tconst userProgress = await getProgress()\n\treturn {\n\t\turi: userProgressUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(userProgress),\n\t}\n}\n\nexport const userProgressResource = {\n\tname: 'user_progress',\n\tdescription: 'The progress of the current user',\n\turiTemplate: userProgressUriTemplate,\n\tgetResource: getUserProgressResource,\n\tinputSchema: userProgressInputSchema,\n}\n\nexport function initResources(server: McpServer) {\n\tserver.registerResource(\n\t\tworkshopContextResource.name,\n\t\tworkshopContextResource.uriTemplate,\n\t\t{ description: workshopContextResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await workshopContextResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn { contents: [resource] }\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseContextResource.name,\n\t\texerciseContextResource.uriTemplate,\n\t\t{ description: exerciseContextResource.description },\n\t\tasync (\n\t\t\t_uri,\n\t\t\t{ workshopDirectory, exerciseNumber: providedExerciseNumber },\n\t\t) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedExerciseNumber === 'string',\n\t\t\t\t'A single exerciseNumber is required',\n\t\t\t)\n\t\t\tconst exerciseNumber = Number(providedExerciseNumber)\n\t\t\tinvariant(!isNaN(exerciseNumber), 'exerciseNumber must be a number')\n\t\t\tinvariant(\n\t\t\t\texerciseNumber >= 0,\n\t\t\t\t'exerciseNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseContextResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tdiffBetweenAppsResource.name,\n\t\tdiffBetweenAppsResource.uriTemplate,\n\t\t{ description: diffBetweenAppsResource.description },\n\t\tasync (_uri, { workshopDirectory, app1, app2 }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(typeof app1 === 'string', 'A single app1 is required')\n\t\t\tinvariant(typeof app2 === 'string', 'A single app2 is required')\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait diffBetweenAppsResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\tapp1,\n\t\t\t\t\t\tapp2,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseStepProgressDiffResource.name,\n\t\texerciseStepProgressDiffResource.uriTemplate,\n\t\t{ description: exerciseStepProgressDiffResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseStepProgressDiffResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserInfoResource.name,\n\t\tuserInfoResource.uriTemplate,\n\t\t{ description: userInfoResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tcontents: [await userInfoResource.getResource({ workshopDirectory })],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserAccessResource.name,\n\t\tuserAccessResource.uriTemplate,\n\t\t{ description: userAccessResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [await userAccessResource.getResource({ workshopDirectory })],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserProgressResource.name,\n\t\tuserProgressResource.uriTemplate,\n\t\t{ description: userProgressResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait userProgressResource.getResource({ workshopDirectory }),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n}\n"]}
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/resources.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path'\nimport { invariant } from '@epic-web/invariant'\nimport {\n\textractNumbersAndTypeFromAppNameOrPath,\n\tfindSolutionDir,\n\tgetApps,\n\tgetExercise,\n\tgetExercises,\n\tgetFullPathFromAppName,\n\tgetPlaygroundApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getAuthInfo } from '@epic-web/workshop-utils/db.server'\nimport {\n\tgetEpicVideoInfos,\n\tuserHasAccessToWorkshop,\n\tgetUserInfo,\n\tgetProgress,\n} from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\ttype McpServer,\n\tResourceTemplate,\n} from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { type ReadResourceResult } from '@modelcontextprotocol/sdk/types.js'\nimport { z } from 'zod'\nimport {\n\thandleWorkshopDirectory,\n\ttype InputSchemaType,\n\treadInWorkshop,\n\tsafeReadFile,\n\tworkshopDirectoryInputSchema,\n} from './utils.js'\n\nexport const getWorkshopContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nexport async function getWorkshopContext({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getWorkshopContextInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\tconst progress = await getProgress()\n\n\tconst output = {\n\t\tmeta: {\n\t\t\t'README.md': await readInWorkshop('README.md'),\n\t\t\tconfig: (\n\t\t\t\tJSON.parse((await readInWorkshop('package.json')) || '{}') as any\n\t\t\t).epicshop,\n\t\t\tinstructions: {\n\t\t\t\tcontent: await readInWorkshop('exercises', 'README.mdx'),\n\t\t\t\tprogress: progress.find((p) => p.type === 'instructions'),\n\t\t\t},\n\t\t\tfinishedInstructions: {\n\t\t\t\tcontent: await readInWorkshop('exercises', 'FINISHED.mdx'),\n\t\t\t\tprogress: progress.find((p) => p.type === 'finished'),\n\t\t\t},\n\t\t},\n\t\texercises: [] as Array<any>,\n\t}\n\n\tconst exercises = await getExercises()\n\tfor (const exercise of exercises) {\n\t\tconst exerciseInfo = {\n\t\t\tfullPath: exercise.fullPath,\n\t\t\texerciseNumber: exercise.exerciseNumber,\n\t\t\ttitle: exercise.title,\n\t\t\tinstructions: {\n\t\t\t\tcontent: await safeReadFile(path.join(exercise.fullPath, 'README.mdx')),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'instructions' &&\n\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\tfinishedInstructions: {\n\t\t\t\tcontent: await safeReadFile(\n\t\t\t\t\tpath.join(exercise.fullPath, 'FINISHED.mdx'),\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'finished' &&\n\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\tsteps: exercise.steps.map((step) => {\n\t\t\t\treturn {\n\t\t\t\t\tstepNumber: step.stepNumber,\n\t\t\t\t\tprogress: progress.find(\n\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\t\t\tp.exerciseNumber === exercise.exerciseNumber &&\n\t\t\t\t\t\t\tp.stepNumber === step.stepNumber,\n\t\t\t\t\t),\n\t\t\t\t\ttitle: step.problem?.title ?? step.solution?.title ?? null,\n\t\t\t\t\tproblem: step.problem\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfullPath: step.problem.fullPath,\n\t\t\t\t\t\t\t\ttestConfig: step.problem.test,\n\t\t\t\t\t\t\t\tdevConfig: step.problem.dev,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: 'No problem app',\n\t\t\t\t\tsolution: step.solution\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfullPath: step.solution.fullPath,\n\t\t\t\t\t\t\t\ttestConfig: step.solution.test,\n\t\t\t\t\t\t\t\tdevConfig: step.solution.dev,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: 'No solution app',\n\t\t\t\t}\n\t\t\t}),\n\t\t}\n\t\toutput.exercises.push(exerciseInfo)\n\t}\n\n\treturn output\n}\n\nconst workshopContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/workshop-context',\n\t{ list: undefined },\n)\n\nexport async function getWorkshopContextResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getWorkshopContextInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: workshopContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(await getWorkshopContext({ workshopDirectory })),\n\t}\n}\n\nexport const workshopContextResource = {\n\tname: 'workshop_context',\n\tdescription: 'The context of the workshop',\n\turiTemplate: workshopContextUriTemplate,\n\tgetResource: getWorkshopContextResource,\n\tinputSchema: getWorkshopContextInputSchema,\n}\n\nconst getExerciseContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\texerciseNumber: z.coerce\n\t\t.number()\n\t\t.optional()\n\t\t.describe(\n\t\t\t`The exercise number to get the context for (defaults to the exercise number the playground is currently set to)`,\n\t\t),\n}\n\nasync function getExerciseContext({\n\tworkshopDirectory,\n\texerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: number\n}) {\n\tconst { userHasAccess, authInfo, progress, numbers } =\n\t\tawait getCommonContextData(workshopDirectory)\n\n\tlet stepNumber = 1\n\tconst isCurrentExercise =\n\t\texerciseNumber === undefined ||\n\t\texerciseNumber === Number(numbers?.exerciseNumber)\n\tif (exerciseNumber === undefined) {\n\t\tinvariant(numbers, 'No numbers found in playground app name')\n\t\texerciseNumber = Number(numbers.exerciseNumber)\n\t\tstepNumber = Number(numbers.stepNumber)\n\t}\n\tconst exercise = await getExercise(exerciseNumber)\n\tinvariant(exercise, `No exercise found for exercise number ${exerciseNumber}`)\n\n\tconst videoInfos = await getEpicVideoInfos([\n\t\t...(exercise.instructionsEpicVideoEmbeds ?? []),\n\t\t...exercise.steps.flatMap((s) => s.problem?.epicVideoEmbeds ?? []),\n\t\t...exercise.steps.flatMap((s) => s.solution?.epicVideoEmbeds ?? []),\n\t\t...(exercise.finishedEpicVideoEmbeds ?? []),\n\t])\n\n\tconst context = {\n\t\tcurrentContext: {\n\t\t\tuser: {\n\t\t\t\thasAccess: userHasAccess,\n\t\t\t\tisAuthenticated: Boolean(authInfo),\n\t\t\t\temail: authInfo?.email,\n\t\t\t},\n\t\t\tplayground: isCurrentExercise\n\t\t\t\t? {\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}\n\t\t\t\t: 'currently set to a different exercise',\n\t\t},\n\t\texerciseInfo: {\n\t\t\tnumber: exerciseNumber,\n\t\t\tintro: {\n\t\t\t\tcontent: await getFileContent(\n\t\t\t\t\tpath.join(exercise.fullPath, 'README.mdx'),\n\t\t\t\t),\n\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\texercise.instructionsEpicVideoEmbeds,\n\t\t\t\t\tvideoInfos,\n\t\t\t\t\tuserHasAccess,\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'instructions' && p.exerciseNumber === exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t\toutro: {\n\t\t\t\tcontent: await getFileContent(\n\t\t\t\t\tpath.join(exercise.fullPath, 'FINISHED.mdx'),\n\t\t\t\t),\n\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\texercise.finishedEpicVideoEmbeds,\n\t\t\t\t\tvideoInfos,\n\t\t\t\t\tuserHasAccess,\n\t\t\t\t),\n\t\t\t\tprogress: progress.find(\n\t\t\t\t\t(p) => p.type === 'finished' && p.exerciseNumber === exerciseNumber,\n\t\t\t\t),\n\t\t\t},\n\t\t},\n\t\tsteps: exercise.steps\n\t\t\t? await Promise.all(\n\t\t\t\t\texercise.steps.map(async (app) => ({\n\t\t\t\t\t\tnumber: app.stepNumber,\n\t\t\t\t\t\tisCurrent: isCurrentExercise && app.stepNumber === stepNumber,\n\t\t\t\t\t\tprogress: progress.find(\n\t\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\t\t\t\tp.exerciseNumber === exerciseNumber &&\n\t\t\t\t\t\t\t\tp.stepNumber === app.stepNumber,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tproblem: {\n\t\t\t\t\t\t\tcontent: app.problem\n\t\t\t\t\t\t\t\t? await getFileContent(\n\t\t\t\t\t\t\t\t\t\tpath.join(app.problem.fullPath, 'README.mdx'),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: 'No problem found',\n\t\t\t\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\t\t\t\tapp.problem?.epicVideoEmbeds,\n\t\t\t\t\t\t\t\tvideoInfos,\n\t\t\t\t\t\t\t\tuserHasAccess,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsolution: {\n\t\t\t\t\t\t\tcontent: app.solution\n\t\t\t\t\t\t\t\t? await getFileContent(\n\t\t\t\t\t\t\t\t\t\tpath.join(app.solution.fullPath, 'README.mdx'),\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: 'No solution found',\n\t\t\t\t\t\t\ttranscripts: getTranscripts(\n\t\t\t\t\t\t\t\tapp.solution?.epicVideoEmbeds,\n\t\t\t\t\t\t\t\tvideoInfos,\n\t\t\t\t\t\t\t\tuserHasAccess,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t})),\n\t\t\t\t)\n\t\t\t: [],\n\t\tnotes: [] as Array<string>,\n\t}\n\n\tif (exercise.steps) {\n\t\tif (isCurrentExercise) {\n\t\t\tcontext.notes.push(\n\t\t\t\t`Reminder, the current step is ${stepNumber} of ${exercise.steps.length + 1}. The most relevant information will be in the context above within the current step.`,\n\t\t\t)\n\t\t}\n\t} else {\n\t\tcontext.notes.push('Unusually, this exercise has no steps.')\n\t}\n\n\treturn context\n}\n\nconst exerciseContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise/{exerciseNumber}',\n\t{ list: undefined },\n)\n\nasync function getExerciseContextResource({\n\tworkshopDirectory,\n\texerciseNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber?: number\n}): Promise<ReadResourceResult['contents'][number]> {\n\tconst context = await getExerciseContext({\n\t\tworkshopDirectory,\n\t\texerciseNumber,\n\t})\n\treturn {\n\t\turi: exerciseContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\texerciseNumber: String(context.exerciseInfo.number),\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(context),\n\t}\n}\n\nexport const exerciseContextResource = {\n\tname: 'exercise_context',\n\tdescription: 'The context of the exercise',\n\turiTemplate: exerciseContextUriTemplate,\n\tgetResource: getExerciseContextResource,\n\tinputSchema: getExerciseContextInputSchema,\n}\n\n// Common helper functions extracted from getExerciseContext\nasync function getCommonContextData(workshopDirectory: string) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\tconst userHasAccess = await userHasAccessToWorkshop()\n\tconst authInfo = await getAuthInfo()\n\tconst progress = await getProgress()\n\tconst playgroundApp = await getPlaygroundApp()\n\tconst numbers = playgroundApp\n\t\t? extractNumbersAndTypeFromAppNameOrPath(playgroundApp.appName)\n\t\t: null\n\n\treturn {\n\t\tuserHasAccess,\n\t\tauthInfo,\n\t\tprogress,\n\t\tplaygroundApp,\n\t\tnumbers,\n\t}\n}\n\nfunction getTranscripts(\n\tembeds: Array<string> | undefined,\n\tvideoInfos: Record<string, any>,\n\tuserHasAccess: boolean,\n) {\n\tif (!embeds) return []\n\tif (!userHasAccess && embeds.length) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tmessage: `User must upgrade before they can get access to ${embeds.length} transcript${embeds.length === 1 ? '' : 's'}.`,\n\t\t\t},\n\t\t]\n\t}\n\treturn embeds.map((embed) => {\n\t\tconst info = videoInfos[embed]\n\t\tif (info) {\n\t\t\tif (info.status === 'error') {\n\t\t\t\tif (info.type === 'region-restricted') {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tembed,\n\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\ttype: info.type,\n\t\t\t\t\t\trequestedCountry: info.requestCountry,\n\t\t\t\t\t\trestrictedCountry: info.restrictedCountry,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tembed,\n\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\ttype: info.type,\n\t\t\t\t\t\tstatusCode: info.statusCode,\n\t\t\t\t\t\tstatusText: info.statusText,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tembed,\n\t\t\t\t\tstatus: 'success',\n\t\t\t\t\ttranscript: info.transcript,\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tembed,\n\t\t\t\tstatus: 'error',\n\t\t\t\ttype: 'not-found',\n\t\t\t\tmessage: 'No transcript found',\n\t\t\t}\n\t\t}\n\t})\n}\n\nasync function getFileContent(filePath: string) {\n\treturn {\n\t\tpath: filePath,\n\t\tcontent: (await safeReadFile(filePath)) ?? 'None found',\n\t}\n}\n\nconst getExerciseStepContextInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\texerciseNumber: z.coerce\n\t\t.number()\n\t\t.describe('The exercise number to get the context for'),\n\tstepNumber: z.coerce\n\t\t.number()\n\t\t.describe('The step number to get the context for'),\n}\n\nasync function getExerciseStepContext({\n\tworkshopDirectory,\n\texerciseNumber,\n\tstepNumber,\n}: {\n\tworkshopDirectory: string\n\texerciseNumber: number\n\tstepNumber: number\n}) {\n\tconst { userHasAccess, authInfo, progress, numbers } =\n\t\tawait getCommonContextData(workshopDirectory)\n\n\tconst isCurrentExercise =\n\t\texerciseNumber === Number(numbers?.exerciseNumber) &&\n\t\tstepNumber === Number(numbers?.stepNumber)\n\n\tconst exercise = await getExercise(exerciseNumber)\n\tinvariant(exercise, `No exercise found for exercise number ${exerciseNumber}`)\n\n\tconst step = exercise.steps.find((s) => s.stepNumber === stepNumber)\n\tinvariant(\n\t\tstep,\n\t\t`No step found for exercise ${exerciseNumber}, step ${stepNumber}`,\n\t)\n\n\tconst videoInfos = await getEpicVideoInfos([\n\t\t...(step.problem?.epicVideoEmbeds ?? []),\n\t\t...(step.solution?.epicVideoEmbeds ?? []),\n\t])\n\n\tconst context = {\n\t\tcurrentContext: {\n\t\t\tuser: {\n\t\t\t\thasAccess: userHasAccess,\n\t\t\t\tisAuthenticated: Boolean(authInfo),\n\t\t\t\temail: authInfo?.email,\n\t\t\t},\n\t\t\tplayground: isCurrentExercise\n\t\t\t\t? {\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}\n\t\t\t\t: 'currently set to a different exercise step',\n\t\t},\n\t\texerciseInfo: {\n\t\t\tnumber: exerciseNumber,\n\t\t\ttitle: exercise.title,\n\t\t},\n\t\tstepInfo: {\n\t\t\tnumber: stepNumber,\n\t\t\tisCurrent: isCurrentExercise,\n\t\t\tprogress: progress.find(\n\t\t\t\t(p) =>\n\t\t\t\t\tp.type === 'step' &&\n\t\t\t\t\tp.exerciseNumber === exerciseNumber &&\n\t\t\t\t\tp.stepNumber === stepNumber,\n\t\t\t),\n\t\t\ttitle: step.problem?.title ?? step.solution?.title ?? null,\n\t\t},\n\t\tproblem: {\n\t\t\tcontent: step.problem\n\t\t\t\t? await getFileContent(path.join(step.problem.fullPath, 'README.mdx'))\n\t\t\t\t: 'No problem found',\n\t\t\ttranscripts: getTranscripts(\n\t\t\t\tstep.problem?.epicVideoEmbeds,\n\t\t\t\tvideoInfos,\n\t\t\t\tuserHasAccess,\n\t\t\t),\n\t\t},\n\t\tsolution: {\n\t\t\tcontent: step.solution\n\t\t\t\t? await getFileContent(path.join(step.solution.fullPath, 'README.mdx'))\n\t\t\t\t: 'No solution found',\n\t\t\ttranscripts: getTranscripts(\n\t\t\t\tstep.solution?.epicVideoEmbeds,\n\t\t\t\tvideoInfos,\n\t\t\t\tuserHasAccess,\n\t\t\t),\n\t\t},\n\t\tnotes: [] as Array<string>,\n\t}\n\n\tif (isCurrentExercise) {\n\t\tcontext.notes.push(\n\t\t\t`This is the current step the user is working on. The playground is set to exercise ${exerciseNumber}, step ${stepNumber}.`,\n\t\t)\n\t}\n\n\treturn context\n}\n\nconst exerciseStepContextUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise/{exerciseNumber}/{stepNumber}',\n\t{ list: undefined },\n)\n\nasync function getExerciseStepContextResource({\n\tworkshopDirectory,\n\texerciseNumber,\n\tstepNumber,\n}: InputSchemaType<typeof getExerciseStepContextInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\tconst context = await getExerciseStepContext({\n\t\tworkshopDirectory,\n\t\texerciseNumber,\n\t\tstepNumber,\n\t})\n\treturn {\n\t\turi: exerciseStepContextUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\texerciseNumber: String(exerciseNumber),\n\t\t\tstepNumber: String(stepNumber),\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(context),\n\t}\n}\n\nexport const exerciseStepContextResource = {\n\tname: 'exercise_step_context',\n\tdescription: 'The context of a specific exercise step',\n\turiTemplate: exerciseStepContextUriTemplate,\n\tgetResource: getExerciseStepContextResource,\n\tinputSchema: getExerciseStepContextInputSchema,\n}\n\nconst diffBetweenAppsInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n\tapp1: z.string().describe('The ID of the first app'),\n\tapp2: z.string().describe('The ID of the second app'),\n}\n\nasync function getDiffBetweenApps({\n\tworkshopDirectory,\n\tapp1,\n\tapp2,\n}: InputSchemaType<typeof diffBetweenAppsInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\n\tconst { getDiffOutputWithRelativePaths } = await import(\n\t\t'@epic-web/workshop-utils/diff.server'\n\t)\n\n\tconst app1Name = extractNumbersAndTypeFromAppNameOrPath(app1)\n\tconst app2Name = extractNumbersAndTypeFromAppNameOrPath(app2)\n\n\tconst apps = await getApps()\n\tconst app1App = apps\n\t\t.filter(isExerciseStepApp)\n\t\t.find(\n\t\t\t(a) =>\n\t\t\t\ta.exerciseNumber === Number(app1Name?.exerciseNumber) &&\n\t\t\t\ta.stepNumber === Number(app1Name?.stepNumber) &&\n\t\t\t\ta.type === app1Name?.type,\n\t\t)\n\tconst app2App = apps\n\t\t.filter(isExerciseStepApp)\n\t\t.find(\n\t\t\t(a) =>\n\t\t\t\ta.exerciseNumber === Number(app2Name?.exerciseNumber) &&\n\t\t\t\ta.stepNumber === Number(app2Name?.stepNumber) &&\n\t\t\t\ta.type === app2Name?.type,\n\t\t)\n\n\tinvariant(app1App, `No app found for ${app1}`)\n\tinvariant(app2App, `No app found for ${app2}`)\n\n\tconst diffCode = await getDiffOutputWithRelativePaths(app1App, app2App)\n\n\tif (!diffCode) return 'No changes'\n\n\treturn diffCode\n}\n\nasync function getDiffBetweenAppsResource({\n\tworkshopDirectory,\n\tapp1,\n\tapp2,\n}: InputSchemaType<typeof diffBetweenAppsInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: diffBetweenAppsUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t\tapp1,\n\t\t\tapp2,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(\n\t\t\tawait getDiffBetweenApps({ workshopDirectory, app1, app2 }),\n\t\t),\n\t}\n}\n\nconst diffBetweenAppsUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/diff-between-apps/{app1}__vs___{app2}',\n\t{ list: undefined },\n)\n\nexport const diffBetweenAppsResource = {\n\tname: 'diff_between_apps',\n\tdescription: 'The diff between two apps',\n\turiTemplate: diffBetweenAppsUriTemplate,\n\tgetResource: getDiffBetweenAppsResource,\n\tinputSchema: diffBetweenAppsInputSchema,\n}\n\nconst getExerciseStepProgressDiffInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nasync function getExerciseStepProgressDiff({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getExerciseStepProgressDiffInputSchema>) {\n\tawait handleWorkshopDirectory(workshopDirectory)\n\n\tconst { getDiffOutputWithRelativePaths } = await import(\n\t\t'@epic-web/workshop-utils/diff.server'\n\t)\n\n\tconst apps = await getApps()\n\tconst playgroundApp = apps.find(isPlaygroundApp)\n\n\tinvariant(playgroundApp, 'No playground app found')\n\n\tconst baseApp = playgroundApp\n\tconst solutionDir = await findSolutionDir({\n\t\tfullPath: await getFullPathFromAppName(playgroundApp.appName),\n\t})\n\tconst headApp = apps.find((a) => a.fullPath === solutionDir)\n\n\tinvariant(headApp, 'No playground solution app found')\n\n\tconst diffCode = await getDiffOutputWithRelativePaths(baseApp, headApp)\n\n\tif (!diffCode) return 'No changes'\n\n\treturn diffCode\n}\n\nconst exerciseStepProgressDiffUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/exercise-step-progress-diff',\n\t{ list: undefined },\n)\n\nasync function getExerciseStepProgressDiffResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getExerciseStepProgressDiffInputSchema>): Promise<\n\tReadResourceResult['contents'][number]\n> {\n\treturn {\n\t\turi: exerciseStepProgressDiffUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(\n\t\t\tawait getExerciseStepProgressDiff({ workshopDirectory }),\n\t\t),\n\t}\n}\n\nexport const exerciseStepProgressDiffResource = {\n\tname: 'exercise_step_progress_diff',\n\tdescription: 'The diff between the current exercise step and the solution',\n\turiTemplate: exerciseStepProgressDiffUriTemplate,\n\tgetResource: getExerciseStepProgressDiffResource,\n\tinputSchema: getExerciseStepProgressDiffInputSchema,\n}\n\nconst getUserInfoInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userInfoUri = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/info',\n\t{ list: undefined },\n)\n\nasync function getUserInfoResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getUserInfoInputSchema>) {\n\tconst userInfo = await getUserInfo()\n\treturn {\n\t\turi: userInfoUri.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(userInfo),\n\t}\n}\n\nexport const userInfoResource = {\n\tname: 'user_info',\n\tdescription: 'Information about the current user',\n\turiTemplate: userInfoUri,\n\tgetResource: getUserInfoResource,\n\tinputSchema: getUserInfoInputSchema,\n}\n\nconst getUserAccessInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userAccessUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/access',\n\t{ list: undefined },\n)\n\nasync function getUserAccessResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof getUserAccessInputSchema>) {\n\tconst userHasAccess = await userHasAccessToWorkshop()\n\treturn {\n\t\turi: userAccessUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify({ userHasAccess }),\n\t}\n}\n\nexport const userAccessResource = {\n\tname: 'user_access',\n\tdescription: 'Whether the current user has access to the workshop',\n\turiTemplate: userAccessUriTemplate,\n\tgetResource: getUserAccessResource,\n\tinputSchema: getUserAccessInputSchema,\n}\n\nconst userProgressInputSchema = {\n\tworkshopDirectory: workshopDirectoryInputSchema,\n}\n\nconst userProgressUriTemplate = new ResourceTemplate(\n\t'epicshop://{workshopDirectory}/user/progress',\n\t{ list: undefined },\n)\n\nasync function getUserProgressResource({\n\tworkshopDirectory,\n}: InputSchemaType<typeof userProgressInputSchema>) {\n\tconst userProgress = await getProgress()\n\treturn {\n\t\turi: userProgressUriTemplate.uriTemplate.expand({\n\t\t\tworkshopDirectory,\n\t\t}),\n\t\tmimeType: 'application/json',\n\t\ttext: JSON.stringify(userProgress),\n\t}\n}\n\nexport const userProgressResource = {\n\tname: 'user_progress',\n\tdescription: 'The progress of the current user',\n\turiTemplate: userProgressUriTemplate,\n\tgetResource: getUserProgressResource,\n\tinputSchema: userProgressInputSchema,\n}\n\nexport function initResources(server: McpServer) {\n\tserver.registerResource(\n\t\tworkshopContextResource.name,\n\t\tworkshopContextResource.uriTemplate,\n\t\t{ description: workshopContextResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\tconst resource = await workshopContextResource.getResource({\n\t\t\t\tworkshopDirectory,\n\t\t\t})\n\t\t\treturn { contents: [resource] }\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseContextResource.name,\n\t\texerciseContextResource.uriTemplate,\n\t\t{ description: exerciseContextResource.description },\n\t\tasync (\n\t\t\t_uri,\n\t\t\t{ workshopDirectory, exerciseNumber: providedExerciseNumber },\n\t\t) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedExerciseNumber === 'string',\n\t\t\t\t'A single exerciseNumber is required',\n\t\t\t)\n\t\t\tconst exerciseNumber = Number(providedExerciseNumber)\n\t\t\tinvariant(!isNaN(exerciseNumber), 'exerciseNumber must be a number')\n\t\t\tinvariant(\n\t\t\t\texerciseNumber >= 0,\n\t\t\t\t'exerciseNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseContextResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseStepContextResource.name,\n\t\texerciseStepContextResource.uriTemplate,\n\t\t{ description: exerciseStepContextResource.description },\n\t\tasync (\n\t\t\t_uri,\n\t\t\t{\n\t\t\t\tworkshopDirectory,\n\t\t\t\texerciseNumber: providedExerciseNumber,\n\t\t\t\tstepNumber: providedStepNumber,\n\t\t\t},\n\t\t) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedExerciseNumber === 'string',\n\t\t\t\t'A single exerciseNumber is required',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\ttypeof providedStepNumber === 'string',\n\t\t\t\t'A single stepNumber is required',\n\t\t\t)\n\t\t\tconst exerciseNumber = Number(providedExerciseNumber)\n\t\t\tconst stepNumber = Number(providedStepNumber)\n\t\t\tinvariant(!isNaN(exerciseNumber), 'exerciseNumber must be a number')\n\t\t\tinvariant(!isNaN(stepNumber), 'stepNumber must be a number')\n\t\t\tinvariant(\n\t\t\t\texerciseNumber >= 0,\n\t\t\t\t'exerciseNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tinvariant(\n\t\t\t\tstepNumber >= 0,\n\t\t\t\t'stepNumber must be greater than or equal to 0',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseStepContextResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tdiffBetweenAppsResource.name,\n\t\tdiffBetweenAppsResource.uriTemplate,\n\t\t{ description: diffBetweenAppsResource.description },\n\t\tasync (_uri, { workshopDirectory, app1, app2 }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tinvariant(typeof app1 === 'string', 'A single app1 is required')\n\t\t\tinvariant(typeof app2 === 'string', 'A single app2 is required')\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait diffBetweenAppsResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t\tapp1,\n\t\t\t\t\t\tapp2,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\texerciseStepProgressDiffResource.name,\n\t\texerciseStepProgressDiffResource.uriTemplate,\n\t\t{ description: exerciseStepProgressDiffResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait exerciseStepProgressDiffResource.getResource({\n\t\t\t\t\t\tworkshopDirectory,\n\t\t\t\t\t}),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserInfoResource.name,\n\t\tuserInfoResource.uriTemplate,\n\t\t{ description: userInfoResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tcontents: [await userInfoResource.getResource({ workshopDirectory })],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserAccessResource.name,\n\t\tuserAccessResource.uriTemplate,\n\t\t{ description: userAccessResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [await userAccessResource.getResource({ workshopDirectory })],\n\t\t\t}\n\t\t},\n\t)\n\n\tserver.registerResource(\n\t\tuserProgressResource.name,\n\t\tuserProgressResource.uriTemplate,\n\t\t{ description: userProgressResource.description },\n\t\tasync (_uri, { workshopDirectory }) => {\n\t\t\tinvariant(\n\t\t\t\ttypeof workshopDirectory === 'string',\n\t\t\t\t'A single workshopDirectory is required',\n\t\t\t)\n\t\t\tworkshopDirectory = await handleWorkshopDirectory(workshopDirectory)\n\t\t\treturn {\n\t\t\t\tcontents: [\n\t\t\t\t\tawait userProgressResource.getResource({ workshopDirectory }),\n\t\t\t\t],\n\t\t\t}\n\t\t},\n\t)\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAsBxE,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,QA4U1C;AAKD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QAuMlD;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QA8BhD"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAA;AA4BxE,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,QAyU1C;AAKD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QA2SlD;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAkQhD"}