pulsemcp-cms-admin-mcp-server 0.9.6 → 0.9.7

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Get available runtimes and exams from the Proctor API
3
+ */
4
+ export async function getProctorMetadata(apiKey, baseUrl) {
5
+ const url = new URL('/api/proctor/metadata', baseUrl);
6
+ const response = await fetch(url.toString(), {
7
+ method: 'GET',
8
+ headers: {
9
+ 'X-API-Key': apiKey,
10
+ Accept: 'application/json',
11
+ },
12
+ });
13
+ if (!response.ok) {
14
+ if (response.status === 401) {
15
+ throw new Error('Invalid API key');
16
+ }
17
+ if (response.status === 403) {
18
+ throw new Error('User lacks admin privileges or insufficient permissions');
19
+ }
20
+ throw new Error(`Failed to get proctor metadata: ${response.status} ${response.statusText}`);
21
+ }
22
+ return (await response.json());
23
+ }
@@ -964,6 +964,12 @@ export function createMockPulseMCPAdminClient(mockData) {
964
964
  pagination: { current_page: 1, total_pages: 1, total_count: 0, has_next: false, limit: 30 },
965
965
  };
966
966
  },
967
+ async getProctorMetadata() {
968
+ return {
969
+ runtimes: [],
970
+ exams: [],
971
+ };
972
+ },
967
973
  // Discovered URL methods
968
974
  async getDiscoveredUrls() {
969
975
  return {
@@ -64,6 +64,7 @@ import { cleanupGoodJobs } from './pulsemcp-admin-client/lib/cleanup-good-jobs.j
64
64
  import { runExamForMirror } from './pulsemcp-admin-client/lib/run-exam-for-mirror.js';
65
65
  import { saveResultsForMirror } from './pulsemcp-admin-client/lib/save-results-for-mirror.js';
66
66
  import { getProctorRuns } from './pulsemcp-admin-client/lib/get-proctor-runs.js';
67
+ import { getProctorMetadata } from './pulsemcp-admin-client/lib/get-proctor-metadata.js';
67
68
  import { getDiscoveredUrls } from './pulsemcp-admin-client/lib/get-discovered-urls.js';
68
69
  import { markDiscoveredUrlProcessed } from './pulsemcp-admin-client/lib/mark-discovered-url-processed.js';
69
70
  import { getDiscoveredUrlStats } from './pulsemcp-admin-client/lib/get-discovered-url-stats.js';
@@ -270,6 +271,9 @@ export class PulseMCPAdminClient {
270
271
  async getProctorRuns(params) {
271
272
  return getProctorRuns(this.apiKey, this.baseUrl, params);
272
273
  }
274
+ async getProctorMetadata() {
275
+ return getProctorMetadata(this.apiKey, this.baseUrl);
276
+ }
273
277
  // Discovered URL REST API methods
274
278
  async getDiscoveredUrls(params) {
275
279
  return getDiscoveredUrls(this.apiKey, this.baseUrl, params);
@@ -0,0 +1,59 @@
1
+ export function getProctorMetadata(_server, clientFactory) {
2
+ return {
3
+ name: 'get_proctor_metadata',
4
+ description: `Get available runtimes and exams for Proctor testing.
5
+
6
+ Returns the list of available runtime environments (Docker images) and exam types.
7
+
8
+ **Returns:**
9
+ - runtimes: Array of runtime configurations with id, name, and Docker image
10
+ - exams: Array of exam types with id, name, and description
11
+
12
+ **Use cases:**
13
+ - Discover available runtime environments and their IDs (needed for run_exam_for_mirror)
14
+ - Find the correct exam ID for a specific test type
15
+ - Check which runtime versions are available`,
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {},
19
+ required: [],
20
+ },
21
+ handler: async () => {
22
+ const client = clientFactory();
23
+ try {
24
+ const response = await client.getProctorMetadata();
25
+ let content = '## Available Proctor Runtimes\n\n';
26
+ for (const runtime of response.runtimes) {
27
+ content += `- **${runtime.name}** (id: \`${runtime.id}\`)\n`;
28
+ content += ` Image: \`${runtime.image}\`\n`;
29
+ }
30
+ content += '\n## Available Exams\n\n';
31
+ for (const exam of response.exams) {
32
+ content += `- **${exam.name}** (id: \`${exam.id}\`)\n`;
33
+ if (exam.description) {
34
+ content += ` ${exam.description}\n`;
35
+ }
36
+ }
37
+ return {
38
+ content: [
39
+ {
40
+ type: 'text',
41
+ text: content.trim(),
42
+ },
43
+ ],
44
+ };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ content: [
49
+ {
50
+ type: 'text',
51
+ text: `Error getting Proctor metadata: ${error instanceof Error ? error.message : String(error)}`,
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+ },
58
+ };
59
+ }
@@ -61,6 +61,7 @@ import { runExamForMirror } from './tools/run-exam-for-mirror.js';
61
61
  import { getExamResult } from './tools/get-exam-result.js';
62
62
  import { saveResultsForMirror } from './tools/save-results-for-mirror.js';
63
63
  import { listProctorRuns } from './tools/list-proctor-runs.js';
64
+ import { getProctorMetadata } from './tools/get-proctor-metadata.js';
64
65
  // Discovered URLs tools
65
66
  import { listDiscoveredUrls } from './tools/list-discovered-urls.js';
66
67
  import { markDiscoveredUrlProcessed } from './tools/mark-discovered-url-processed.js';
@@ -232,6 +233,7 @@ const ALL_TOOLS = [
232
233
  { factory: getExamResult, groups: ['proctor'], isWriteOperation: false },
233
234
  { factory: saveResultsForMirror, groups: ['proctor'], isWriteOperation: true },
234
235
  { factory: listProctorRuns, groups: ['proctor'], isWriteOperation: false },
236
+ { factory: getProctorMetadata, groups: ['proctor'], isWriteOperation: false },
235
237
  // Discovered URLs tools
236
238
  { factory: listDiscoveredUrls, groups: ['discovered_urls'], isWriteOperation: false },
237
239
  {
@@ -369,7 +371,7 @@ function shouldIncludeTool(toolDef, enabledGroups) {
369
371
  * - good_jobs: GoodJob background job management tools (read + write)
370
372
  * - good_jobs_readonly: GoodJob tools (read only)
371
373
  * - proctor: Proctor exam execution and result storage tools (read + write)
372
- * - proctor_readonly: Proctor tools (read only - get_exam_result and list_proctor_runs)
374
+ * - proctor_readonly: Proctor tools (read only - get_exam_result, list_proctor_runs, and get_proctor_metadata)
373
375
  * - discovered_urls: Discovered URL management tools for processing URLs into MCP implementations (read + write)
374
376
  * - discovered_urls_readonly: Discovered URL tools (read only - list and stats)
375
377
  * - notifications: Notification email tools - send_impl_posted_notif (write-only, no readonly variant)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulsemcp-cms-admin-mcp-server",
3
- "version": "0.9.6",
3
+ "version": "0.9.7",
4
4
  "description": "Local implementation of PulseMCP CMS Admin MCP server",
5
5
  "mcpName": "com.pulsemcp.servers/pulsemcp-cms-admin",
6
6
  "main": "build/index.js",
@@ -0,0 +1,6 @@
1
+ import type { ProctorMetadataResponse } from '../../types.js';
2
+ /**
3
+ * Get available runtimes and exams from the Proctor API
4
+ */
5
+ export declare function getProctorMetadata(apiKey: string, baseUrl: string): Promise<ProctorMetadataResponse>;
6
+ //# sourceMappingURL=get-proctor-metadata.d.ts.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Get available runtimes and exams from the Proctor API
3
+ */
4
+ export async function getProctorMetadata(apiKey, baseUrl) {
5
+ const url = new URL('/api/proctor/metadata', baseUrl);
6
+ const response = await fetch(url.toString(), {
7
+ method: 'GET',
8
+ headers: {
9
+ 'X-API-Key': apiKey,
10
+ Accept: 'application/json',
11
+ },
12
+ });
13
+ if (!response.ok) {
14
+ if (response.status === 401) {
15
+ throw new Error('Invalid API key');
16
+ }
17
+ if (response.status === 403) {
18
+ throw new Error('User lacks admin privileges or insufficient permissions');
19
+ }
20
+ throw new Error(`Failed to get proctor metadata: ${response.status} ${response.statusText}`);
21
+ }
22
+ return (await response.json());
23
+ }
@@ -964,6 +964,12 @@ export function createMockPulseMCPAdminClient(mockData) {
964
964
  pagination: { current_page: 1, total_pages: 1, total_count: 0, has_next: false, limit: 30 },
965
965
  };
966
966
  },
967
+ async getProctorMetadata() {
968
+ return {
969
+ runtimes: [],
970
+ exams: [],
971
+ };
972
+ },
967
973
  // Discovered URL methods
968
974
  async getDiscoveredUrls() {
969
975
  return {
@@ -1,5 +1,5 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
- import type { Post, PostsResponse, CreatePostParams, UpdatePostParams, ImageUploadResponse, Author, AuthorsResponse, MCPServer, MCPClient, MCPImplementation, MCPImplementationsResponse, SaveMCPImplementationParams, CreateMCPImplementationParams, Provider, ProvidersResponse, OfficialMirrorQueueStatus, OfficialMirrorQueueResponse, OfficialMirrorQueueItemDetail, OfficialMirrorQueueActionResponse, UnofficialMirror, UnofficialMirrorsResponse, CreateUnofficialMirrorParams, UpdateUnofficialMirrorParams, OfficialMirrorRest, OfficialMirrorsResponse, Tenant, TenantsResponse, McpJson, McpJsonsResponse, CreateMcpJsonParams, UpdateMcpJsonParams, UnifiedMCPServer, UnifiedMCPServersResponse, UpdateUnifiedMCPServerParams, Redirect, RedirectsResponse, RedirectStatus, CreateRedirectParams, UpdateRedirectParams, GoodJob, GoodJobsResponse, GoodJobStatus, GoodJobCronSchedule, GoodJobProcess, GoodJobStatistics, GoodJobActionResponse, GoodJobCleanupResponse, ProctorRunExamParams, ProctorRunExamResponse, ProctorSaveResultsParams, ProctorSaveResultsResponse, ProctorRunsResponse, GetProctorRunsParams, DiscoveredUrlsResponse, MarkDiscoveredUrlProcessedParams, MarkDiscoveredUrlProcessedResponse, DiscoveredUrlStats } from './types.js';
2
+ import type { Post, PostsResponse, CreatePostParams, UpdatePostParams, ImageUploadResponse, Author, AuthorsResponse, MCPServer, MCPClient, MCPImplementation, MCPImplementationsResponse, SaveMCPImplementationParams, CreateMCPImplementationParams, Provider, ProvidersResponse, OfficialMirrorQueueStatus, OfficialMirrorQueueResponse, OfficialMirrorQueueItemDetail, OfficialMirrorQueueActionResponse, UnofficialMirror, UnofficialMirrorsResponse, CreateUnofficialMirrorParams, UpdateUnofficialMirrorParams, OfficialMirrorRest, OfficialMirrorsResponse, Tenant, TenantsResponse, McpJson, McpJsonsResponse, CreateMcpJsonParams, UpdateMcpJsonParams, UnifiedMCPServer, UnifiedMCPServersResponse, UpdateUnifiedMCPServerParams, Redirect, RedirectsResponse, RedirectStatus, CreateRedirectParams, UpdateRedirectParams, GoodJob, GoodJobsResponse, GoodJobStatus, GoodJobCronSchedule, GoodJobProcess, GoodJobStatistics, GoodJobActionResponse, GoodJobCleanupResponse, ProctorRunExamParams, ProctorRunExamResponse, ProctorSaveResultsParams, ProctorSaveResultsResponse, ProctorRunsResponse, GetProctorRunsParams, ProctorMetadataResponse, DiscoveredUrlsResponse, MarkDiscoveredUrlProcessedParams, MarkDiscoveredUrlProcessedResponse, DiscoveredUrlStats } from './types.js';
3
3
  export interface IPulseMCPAdminClient {
4
4
  getPosts(params?: {
5
5
  search?: string;
@@ -161,6 +161,7 @@ export interface IPulseMCPAdminClient {
161
161
  runExamForMirror(params: ProctorRunExamParams): Promise<ProctorRunExamResponse>;
162
162
  saveResultsForMirror(params: ProctorSaveResultsParams): Promise<ProctorSaveResultsResponse>;
163
163
  getProctorRuns(params?: GetProctorRunsParams): Promise<ProctorRunsResponse>;
164
+ getProctorMetadata(): Promise<ProctorMetadataResponse>;
164
165
  getDiscoveredUrls(params?: {
165
166
  status?: 'pending' | 'processed' | 'all';
166
167
  page?: number;
@@ -333,6 +334,7 @@ export declare class PulseMCPAdminClient implements IPulseMCPAdminClient {
333
334
  runExamForMirror(params: ProctorRunExamParams): Promise<ProctorRunExamResponse>;
334
335
  saveResultsForMirror(params: ProctorSaveResultsParams): Promise<ProctorSaveResultsResponse>;
335
336
  getProctorRuns(params?: GetProctorRunsParams): Promise<ProctorRunsResponse>;
337
+ getProctorMetadata(): Promise<ProctorMetadataResponse>;
336
338
  getDiscoveredUrls(params?: {
337
339
  status?: 'pending' | 'processed' | 'all';
338
340
  page?: number;
package/shared/server.js CHANGED
@@ -64,6 +64,7 @@ import { cleanupGoodJobs } from './pulsemcp-admin-client/lib/cleanup-good-jobs.j
64
64
  import { runExamForMirror } from './pulsemcp-admin-client/lib/run-exam-for-mirror.js';
65
65
  import { saveResultsForMirror } from './pulsemcp-admin-client/lib/save-results-for-mirror.js';
66
66
  import { getProctorRuns } from './pulsemcp-admin-client/lib/get-proctor-runs.js';
67
+ import { getProctorMetadata } from './pulsemcp-admin-client/lib/get-proctor-metadata.js';
67
68
  import { getDiscoveredUrls } from './pulsemcp-admin-client/lib/get-discovered-urls.js';
68
69
  import { markDiscoveredUrlProcessed } from './pulsemcp-admin-client/lib/mark-discovered-url-processed.js';
69
70
  import { getDiscoveredUrlStats } from './pulsemcp-admin-client/lib/get-discovered-url-stats.js';
@@ -270,6 +271,9 @@ export class PulseMCPAdminClient {
270
271
  async getProctorRuns(params) {
271
272
  return getProctorRuns(this.apiKey, this.baseUrl, params);
272
273
  }
274
+ async getProctorMetadata() {
275
+ return getProctorMetadata(this.apiKey, this.baseUrl);
276
+ }
273
277
  // Discovered URL REST API methods
274
278
  async getDiscoveredUrls(params) {
275
279
  return getDiscoveredUrls(this.apiKey, this.baseUrl, params);
@@ -0,0 +1,25 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import type { ClientFactory } from '../server.js';
3
+ export declare function getProctorMetadata(_server: Server, clientFactory: ClientFactory): {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: {
7
+ type: string;
8
+ properties: {};
9
+ required: never[];
10
+ };
11
+ handler: () => Promise<{
12
+ content: {
13
+ type: string;
14
+ text: string;
15
+ }[];
16
+ isError?: undefined;
17
+ } | {
18
+ content: {
19
+ type: string;
20
+ text: string;
21
+ }[];
22
+ isError: boolean;
23
+ }>;
24
+ };
25
+ //# sourceMappingURL=get-proctor-metadata.d.ts.map
@@ -0,0 +1,59 @@
1
+ export function getProctorMetadata(_server, clientFactory) {
2
+ return {
3
+ name: 'get_proctor_metadata',
4
+ description: `Get available runtimes and exams for Proctor testing.
5
+
6
+ Returns the list of available runtime environments (Docker images) and exam types.
7
+
8
+ **Returns:**
9
+ - runtimes: Array of runtime configurations with id, name, and Docker image
10
+ - exams: Array of exam types with id, name, and description
11
+
12
+ **Use cases:**
13
+ - Discover available runtime environments and their IDs (needed for run_exam_for_mirror)
14
+ - Find the correct exam ID for a specific test type
15
+ - Check which runtime versions are available`,
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {},
19
+ required: [],
20
+ },
21
+ handler: async () => {
22
+ const client = clientFactory();
23
+ try {
24
+ const response = await client.getProctorMetadata();
25
+ let content = '## Available Proctor Runtimes\n\n';
26
+ for (const runtime of response.runtimes) {
27
+ content += `- **${runtime.name}** (id: \`${runtime.id}\`)\n`;
28
+ content += ` Image: \`${runtime.image}\`\n`;
29
+ }
30
+ content += '\n## Available Exams\n\n';
31
+ for (const exam of response.exams) {
32
+ content += `- **${exam.name}** (id: \`${exam.id}\`)\n`;
33
+ if (exam.description) {
34
+ content += ` ${exam.description}\n`;
35
+ }
36
+ }
37
+ return {
38
+ content: [
39
+ {
40
+ type: 'text',
41
+ text: content.trim(),
42
+ },
43
+ ],
44
+ };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ content: [
49
+ {
50
+ type: 'text',
51
+ text: `Error getting Proctor metadata: ${error instanceof Error ? error.message : String(error)}`,
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+ },
58
+ };
59
+ }
package/shared/tools.d.ts CHANGED
@@ -23,7 +23,7 @@ import { ClientFactory } from './server.js';
23
23
  * - mcp_servers / mcp_servers_readonly: Unified MCP server tools (abstracted interface)
24
24
  * - redirects / redirects_readonly: URL redirect management tools
25
25
  * - good_jobs / good_jobs_readonly: GoodJob background job management tools
26
- * - proctor / proctor_readonly: Proctor exam execution and result storage tools. The readonly variant includes get_exam_result and list_proctor_runs for retrieving stored results without running exams or saving
26
+ * - proctor / proctor_readonly: Proctor exam execution and result storage tools. The readonly variant includes get_exam_result, list_proctor_runs, and get_proctor_metadata for retrieving stored results and metadata without running exams or saving
27
27
  * - discovered_urls / discovered_urls_readonly: Discovered URL management tools for processing URLs into MCP implementations
28
28
  * - notifications: Notification email tools (send_impl_posted_notif). Separated from server_directory so notification capability can be granted independently.
29
29
  */
@@ -69,7 +69,7 @@ export declare function parseEnabledToolGroups(enabledGroupsParam?: string): Too
69
69
  * - good_jobs: GoodJob background job management tools (read + write)
70
70
  * - good_jobs_readonly: GoodJob tools (read only)
71
71
  * - proctor: Proctor exam execution and result storage tools (read + write)
72
- * - proctor_readonly: Proctor tools (read only - get_exam_result and list_proctor_runs)
72
+ * - proctor_readonly: Proctor tools (read only - get_exam_result, list_proctor_runs, and get_proctor_metadata)
73
73
  * - discovered_urls: Discovered URL management tools for processing URLs into MCP implementations (read + write)
74
74
  * - discovered_urls_readonly: Discovered URL tools (read only - list and stats)
75
75
  * - notifications: Notification email tools - send_impl_posted_notif (write-only, no readonly variant)
package/shared/tools.js CHANGED
@@ -61,6 +61,7 @@ import { runExamForMirror } from './tools/run-exam-for-mirror.js';
61
61
  import { getExamResult } from './tools/get-exam-result.js';
62
62
  import { saveResultsForMirror } from './tools/save-results-for-mirror.js';
63
63
  import { listProctorRuns } from './tools/list-proctor-runs.js';
64
+ import { getProctorMetadata } from './tools/get-proctor-metadata.js';
64
65
  // Discovered URLs tools
65
66
  import { listDiscoveredUrls } from './tools/list-discovered-urls.js';
66
67
  import { markDiscoveredUrlProcessed } from './tools/mark-discovered-url-processed.js';
@@ -232,6 +233,7 @@ const ALL_TOOLS = [
232
233
  { factory: getExamResult, groups: ['proctor'], isWriteOperation: false },
233
234
  { factory: saveResultsForMirror, groups: ['proctor'], isWriteOperation: true },
234
235
  { factory: listProctorRuns, groups: ['proctor'], isWriteOperation: false },
236
+ { factory: getProctorMetadata, groups: ['proctor'], isWriteOperation: false },
235
237
  // Discovered URLs tools
236
238
  { factory: listDiscoveredUrls, groups: ['discovered_urls'], isWriteOperation: false },
237
239
  {
@@ -369,7 +371,7 @@ function shouldIncludeTool(toolDef, enabledGroups) {
369
371
  * - good_jobs: GoodJob background job management tools (read + write)
370
372
  * - good_jobs_readonly: GoodJob tools (read only)
371
373
  * - proctor: Proctor exam execution and result storage tools (read + write)
372
- * - proctor_readonly: Proctor tools (read only - get_exam_result and list_proctor_runs)
374
+ * - proctor_readonly: Proctor tools (read only - get_exam_result, list_proctor_runs, and get_proctor_metadata)
373
375
  * - discovered_urls: Discovered URL management tools for processing URLs into MCP implementations (read + write)
374
376
  * - discovered_urls_readonly: Discovered URL tools (read only - list and stats)
375
377
  * - notifications: Notification email tools - send_impl_posted_notif (write-only, no readonly variant)
package/shared/types.d.ts CHANGED
@@ -736,6 +736,20 @@ export interface GetProctorRunsParams {
736
736
  limit?: number;
737
737
  offset?: number;
738
738
  }
739
+ export interface ProctorRuntime {
740
+ id: string;
741
+ name: string;
742
+ image: string;
743
+ }
744
+ export interface ProctorExam {
745
+ id: string;
746
+ name: string;
747
+ description: string;
748
+ }
749
+ export interface ProctorMetadataResponse {
750
+ runtimes: ProctorRuntime[];
751
+ exams: ProctorExam[];
752
+ }
739
753
  export type DiscoveredUrlResult = 'posted' | 'skipped' | 'rejected' | 'error';
740
754
  export interface DiscoveredUrl {
741
755
  id: number;