pulsemcp-cms-admin-mcp-server 0.5.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +78 -34
  2. package/build/shared/src/pulsemcp-admin-client/lib/create-mcp-json.js +46 -0
  3. package/build/shared/src/pulsemcp-admin-client/lib/create-unofficial-mirror.js +55 -0
  4. package/build/shared/src/pulsemcp-admin-client/lib/delete-mcp-json.js +24 -0
  5. package/build/shared/src/pulsemcp-admin-client/lib/delete-unofficial-mirror.js +24 -0
  6. package/build/shared/src/pulsemcp-admin-client/lib/get-mcp-json.js +35 -0
  7. package/build/shared/src/pulsemcp-admin-client/lib/get-mcp-jsons.js +56 -0
  8. package/build/shared/src/pulsemcp-admin-client/lib/get-official-mirror.js +39 -0
  9. package/build/shared/src/pulsemcp-admin-client/lib/get-official-mirrors.js +66 -0
  10. package/build/shared/src/pulsemcp-admin-client/lib/get-tenant.js +31 -0
  11. package/build/shared/src/pulsemcp-admin-client/lib/get-tenants.js +52 -0
  12. package/build/shared/src/pulsemcp-admin-client/lib/get-unified-mcp-server.js +93 -0
  13. package/build/shared/src/pulsemcp-admin-client/lib/get-unified-mcp-servers.js +51 -0
  14. package/build/shared/src/pulsemcp-admin-client/lib/get-unofficial-mirror.js +38 -0
  15. package/build/shared/src/pulsemcp-admin-client/lib/get-unofficial-mirrors.js +59 -0
  16. package/build/shared/src/pulsemcp-admin-client/lib/save-mcp-implementation.js +27 -0
  17. package/build/shared/src/pulsemcp-admin-client/lib/unified-mcp-server-mapper.js +81 -0
  18. package/build/shared/src/pulsemcp-admin-client/lib/update-mcp-json.js +54 -0
  19. package/build/shared/src/pulsemcp-admin-client/lib/update-unified-mcp-server.js +90 -0
  20. package/build/shared/src/pulsemcp-admin-client/lib/update-unofficial-mirror.js +64 -0
  21. package/build/shared/src/pulsemcp-admin-client/pulsemcp-admin-client.integration-mock.js +160 -0
  22. package/build/shared/src/server.js +73 -0
  23. package/build/shared/src/tools/create-mcp-json.js +92 -0
  24. package/build/shared/src/tools/create-unofficial-mirror.js +93 -0
  25. package/build/shared/src/tools/delete-mcp-json.js +51 -0
  26. package/build/shared/src/tools/delete-unofficial-mirror.js +51 -0
  27. package/build/shared/src/tools/get-mcp-json.js +81 -0
  28. package/build/shared/src/tools/get-mcp-jsons.js +183 -0
  29. package/build/shared/src/tools/get-mcp-server.js +246 -0
  30. package/build/shared/src/tools/get-official-mirror.js +109 -0
  31. package/build/shared/src/tools/get-official-mirrors.js +106 -0
  32. package/build/shared/src/tools/get-tenant.js +71 -0
  33. package/build/shared/src/tools/get-tenants.js +82 -0
  34. package/build/shared/src/tools/get-unofficial-mirror.js +106 -0
  35. package/build/shared/src/tools/get-unofficial-mirrors.js +105 -0
  36. package/build/shared/src/tools/list-mcp-servers.js +146 -0
  37. package/build/shared/src/tools/update-mcp-json.js +112 -0
  38. package/build/shared/src/tools/update-mcp-server.js +340 -0
  39. package/build/shared/src/tools/update-unofficial-mirror.js +109 -0
  40. package/build/shared/src/tools.js +72 -1
  41. package/package.json +1 -1
  42. package/shared/pulsemcp-admin-client/lib/create-mcp-json.d.ts +3 -0
  43. package/shared/pulsemcp-admin-client/lib/create-mcp-json.js +46 -0
  44. package/shared/pulsemcp-admin-client/lib/create-unofficial-mirror.d.ts +3 -0
  45. package/shared/pulsemcp-admin-client/lib/create-unofficial-mirror.js +55 -0
  46. package/shared/pulsemcp-admin-client/lib/delete-mcp-json.d.ts +5 -0
  47. package/shared/pulsemcp-admin-client/lib/delete-mcp-json.js +24 -0
  48. package/shared/pulsemcp-admin-client/lib/delete-unofficial-mirror.d.ts +5 -0
  49. package/shared/pulsemcp-admin-client/lib/delete-unofficial-mirror.js +24 -0
  50. package/shared/pulsemcp-admin-client/lib/get-mcp-json.d.ts +3 -0
  51. package/shared/pulsemcp-admin-client/lib/get-mcp-json.js +35 -0
  52. package/shared/pulsemcp-admin-client/lib/get-mcp-jsons.d.ts +8 -0
  53. package/shared/pulsemcp-admin-client/lib/get-mcp-jsons.js +56 -0
  54. package/shared/pulsemcp-admin-client/lib/get-official-mirror.d.ts +3 -0
  55. package/shared/pulsemcp-admin-client/lib/get-official-mirror.js +39 -0
  56. package/shared/pulsemcp-admin-client/lib/get-official-mirrors.d.ts +10 -0
  57. package/shared/pulsemcp-admin-client/lib/get-official-mirrors.js +66 -0
  58. package/shared/pulsemcp-admin-client/lib/get-tenant.d.ts +3 -0
  59. package/shared/pulsemcp-admin-client/lib/get-tenant.js +31 -0
  60. package/shared/pulsemcp-admin-client/lib/get-tenants.d.ts +8 -0
  61. package/shared/pulsemcp-admin-client/lib/get-tenants.js +52 -0
  62. package/shared/pulsemcp-admin-client/lib/get-unified-mcp-server.d.ts +7 -0
  63. package/shared/pulsemcp-admin-client/lib/get-unified-mcp-server.js +93 -0
  64. package/shared/pulsemcp-admin-client/lib/get-unified-mcp-servers.d.ts +9 -0
  65. package/shared/pulsemcp-admin-client/lib/get-unified-mcp-servers.js +51 -0
  66. package/shared/pulsemcp-admin-client/lib/get-unofficial-mirror.d.ts +3 -0
  67. package/shared/pulsemcp-admin-client/lib/get-unofficial-mirror.js +38 -0
  68. package/shared/pulsemcp-admin-client/lib/get-unofficial-mirrors.d.ts +8 -0
  69. package/shared/pulsemcp-admin-client/lib/get-unofficial-mirrors.js +59 -0
  70. package/shared/pulsemcp-admin-client/lib/save-mcp-implementation.js +27 -0
  71. package/shared/pulsemcp-admin-client/lib/unified-mcp-server-mapper.d.ts +72 -0
  72. package/shared/pulsemcp-admin-client/lib/unified-mcp-server-mapper.js +81 -0
  73. package/shared/pulsemcp-admin-client/lib/update-mcp-json.d.ts +3 -0
  74. package/shared/pulsemcp-admin-client/lib/update-mcp-json.js +54 -0
  75. package/shared/pulsemcp-admin-client/lib/update-unified-mcp-server.d.ts +7 -0
  76. package/shared/pulsemcp-admin-client/lib/update-unified-mcp-server.js +90 -0
  77. package/shared/pulsemcp-admin-client/lib/update-unofficial-mirror.d.ts +3 -0
  78. package/shared/pulsemcp-admin-client/lib/update-unofficial-mirror.js +64 -0
  79. package/shared/pulsemcp-admin-client/pulsemcp-admin-client.integration-mock.js +160 -0
  80. package/shared/server.d.ts +103 -1
  81. package/shared/server.js +73 -0
  82. package/shared/tools/create-mcp-json.d.ts +44 -0
  83. package/shared/tools/create-mcp-json.js +92 -0
  84. package/shared/tools/create-unofficial-mirror.d.ts +52 -0
  85. package/shared/tools/create-unofficial-mirror.js +93 -0
  86. package/shared/tools/delete-mcp-json.d.ts +30 -0
  87. package/shared/tools/delete-mcp-json.js +51 -0
  88. package/shared/tools/delete-unofficial-mirror.d.ts +30 -0
  89. package/shared/tools/delete-unofficial-mirror.js +51 -0
  90. package/shared/tools/get-mcp-json.d.ts +30 -0
  91. package/shared/tools/get-mcp-json.js +81 -0
  92. package/shared/tools/get-mcp-jsons.d.ts +56 -0
  93. package/shared/tools/get-mcp-jsons.js +183 -0
  94. package/shared/tools/get-mcp-server.d.ts +30 -0
  95. package/shared/tools/get-mcp-server.js +246 -0
  96. package/shared/tools/get-official-mirror.d.ts +33 -0
  97. package/shared/tools/get-official-mirror.js +109 -0
  98. package/shared/tools/get-official-mirrors.d.ts +52 -0
  99. package/shared/tools/get-official-mirrors.js +106 -0
  100. package/shared/tools/get-tenant.d.ts +32 -0
  101. package/shared/tools/get-tenant.js +71 -0
  102. package/shared/tools/get-tenants.d.ts +44 -0
  103. package/shared/tools/get-tenants.js +82 -0
  104. package/shared/tools/get-unofficial-mirror.d.ts +33 -0
  105. package/shared/tools/get-unofficial-mirror.js +106 -0
  106. package/shared/tools/get-unofficial-mirrors.d.ts +48 -0
  107. package/shared/tools/get-unofficial-mirrors.js +105 -0
  108. package/shared/tools/list-mcp-servers.d.ts +50 -0
  109. package/shared/tools/list-mcp-servers.js +146 -0
  110. package/shared/tools/update-mcp-json.d.ts +48 -0
  111. package/shared/tools/update-mcp-json.js +112 -0
  112. package/shared/tools/update-mcp-server.d.ts +199 -0
  113. package/shared/tools/update-mcp-server.js +340 -0
  114. package/shared/tools/update-unofficial-mirror.d.ts +56 -0
  115. package/shared/tools/update-unofficial-mirror.js +109 -0
  116. package/shared/tools.d.ts +14 -1
  117. package/shared/tools.js +72 -1
  118. package/shared/types.d.ts +237 -0
package/README.md CHANGED
@@ -40,26 +40,43 @@ This is an MCP ([Model Context Protocol](https://modelcontextprotocol.io/)) Serv
40
40
 
41
41
  This server is built and tested on macOS with Claude Desktop. It should work with other MCP clients as well.
42
42
 
43
- | Tool Name | Tool Group | Read/Write | Description |
44
- | -------------------------------------- | -------------- | ---------- | ---------------------------------------------------------------------------- |
45
- | `get_newsletter_posts` | newsletter | read | List newsletter posts with search, sorting, and pagination options. |
46
- | `get_newsletter_post` | newsletter | read | Retrieve a specific newsletter post by its unique slug. |
47
- | `draft_newsletter_post` | newsletter | write | Create a new draft newsletter post with title, body, and metadata. |
48
- | `update_newsletter_post` | newsletter | write | Update an existing newsletter post's content and metadata (except status). |
49
- | `upload_image` | newsletter | write | Upload an image and attach it to a specific newsletter post. |
50
- | `get_authors` | newsletter | read | Get a list of authors with optional search and pagination. |
51
- | `search_mcp_implementations` | server_queue | read | Search for MCP servers and clients in the PulseMCP registry. |
52
- | `get_draft_mcp_implementations` | server_queue | read | Retrieve paginated list of draft MCP implementations needing review. |
53
- | `find_providers` | server_queue | read | Search for providers by ID, name, URL, or slug. |
54
- | `save_mcp_implementation` | server_queue | write | Update an MCP implementation (replicates Admin panel "Save Changes" button). |
55
- | `send_impl_posted_notif` | server_queue | write | Send email notification when MCP implementation goes live. |
56
- | `get_official_mirror_queue_items` | official_queue | read | List and filter official mirror queue entries with pagination and search. |
57
- | `get_official_mirror_queue_item` | official_queue | read | Get detailed information about a single official mirror queue entry. |
58
- | `approve_official_mirror_queue_item` | official_queue | write | Approve a queue entry and link it to an existing MCP server (async). |
59
- | `approve_mirror_no_modify` | official_queue | write | Approve without updating the linked server. |
60
- | `reject_official_mirror_queue_item` | official_queue | write | Reject a queue entry (async operation). |
61
- | `add_official_mirror_to_regular_queue` | official_queue | write | Convert a queue entry to a draft MCP implementation (async). |
62
- | `unlink_official_mirror_queue_item` | official_queue | write | Unlink a queue entry from its linked MCP server. |
43
+ | Tool Name | Tool Group | Read/Write | Description |
44
+ | -------------------------------------- | ------------------ | ---------- | ----------------------------------------------------------------------------- |
45
+ | `get_newsletter_posts` | newsletter | read | List newsletter posts with search, sorting, and pagination options. |
46
+ | `get_newsletter_post` | newsletter | read | Retrieve a specific newsletter post by its unique slug. |
47
+ | `draft_newsletter_post` | newsletter | write | Create a new draft newsletter post with title, body, and metadata. |
48
+ | `update_newsletter_post` | newsletter | write | Update an existing newsletter post's content and metadata (except status). |
49
+ | `upload_image` | newsletter | write | Upload an image and attach it to a specific newsletter post. |
50
+ | `get_authors` | newsletter | read | Get a list of authors with optional search and pagination. |
51
+ | `search_mcp_implementations` | server_queue | read | Search for MCP servers and clients in the PulseMCP registry. |
52
+ | `get_draft_mcp_implementations` | server_queue | read | Retrieve paginated list of draft MCP implementations needing review. |
53
+ | `find_providers` | server_queue | read | Search for providers by ID, name, URL, or slug. |
54
+ | `save_mcp_implementation` | server_queue | write | Update an MCP implementation (replicates Admin panel "Save Changes" button). |
55
+ | `send_impl_posted_notif` | server_queue | write | Send email notification when MCP implementation goes live. |
56
+ | `get_official_mirror_queue_items` | official_queue | read | List and filter official mirror queue entries with pagination and search. |
57
+ | `get_official_mirror_queue_item` | official_queue | read | Get detailed information about a single official mirror queue entry. |
58
+ | `approve_official_mirror_queue_item` | official_queue | write | Approve a queue entry and link it to an existing MCP server (async). |
59
+ | `approve_mirror_no_modify` | official_queue | write | Approve without updating the linked server. |
60
+ | `reject_official_mirror_queue_item` | official_queue | write | Reject a queue entry (async operation). |
61
+ | `add_official_mirror_to_regular_queue` | official_queue | write | Convert a queue entry to a draft MCP implementation (async). |
62
+ | `unlink_official_mirror_queue_item` | official_queue | write | Unlink a queue entry from its linked MCP server. |
63
+ | `get_unofficial_mirrors` | unofficial_mirrors | read | List unofficial mirrors with search, pagination, and MCP server filtering. |
64
+ | `get_unofficial_mirror` | unofficial_mirrors | read | Get detailed unofficial mirror info by ID or name. |
65
+ | `create_unofficial_mirror` | unofficial_mirrors | write | Create a new unofficial mirror entry with JSON data. |
66
+ | `update_unofficial_mirror` | unofficial_mirrors | write | Update an existing unofficial mirror by ID. |
67
+ | `delete_unofficial_mirror` | unofficial_mirrors | write | Delete an unofficial mirror by ID (irreversible). |
68
+ | `get_official_mirrors` | official_mirrors | read | List official mirrors with search, status, and processing filters. |
69
+ | `get_official_mirror` | official_mirrors | read | Get detailed official mirror info by ID or name. |
70
+ | `get_tenants` | tenants | read | List tenants with search and admin status filtering. |
71
+ | `get_tenant` | tenants | read | Get detailed tenant info by ID or slug. |
72
+ | `get_mcp_jsons` | mcp_jsons | read | List MCP JSON configs with mirror and server filtering. |
73
+ | `get_mcp_json` | mcp_jsons | read | Get a single MCP JSON configuration by ID. |
74
+ | `create_mcp_json` | mcp_jsons | write | Create a new MCP JSON configuration for an unofficial mirror. |
75
+ | `update_mcp_json` | mcp_jsons | write | Update an existing MCP JSON configuration by ID. |
76
+ | `delete_mcp_json` | mcp_jsons | write | Delete an MCP JSON configuration by ID (irreversible). |
77
+ | `list_mcp_servers` | mcp_servers | read | List/search MCP servers with filtering by status, classification, pagination. |
78
+ | `get_mcp_server` | mcp_servers | read | Get detailed MCP server info by slug (unified view of all admin UI fields). |
79
+ | `update_mcp_server` | mcp_servers | write | Update an MCP server's fields (all admin UI fields supported). |
63
80
 
64
81
  # Tool Groups
65
82
 
@@ -70,14 +87,24 @@ This server organizes tools into groups that can be selectively enabled or disab
70
87
 
71
88
  ## Available Groups
72
89
 
73
- | Group | Tools | Description |
74
- | ------------------------- | ----- | -------------------------------------------- |
75
- | `newsletter` | 6 | Full newsletter management (read + write) |
76
- | `newsletter_readonly` | 3 | Newsletter read-only (get posts, authors) |
77
- | `server_queue` | 5 | Full MCP implementation queue (read + write) |
78
- | `server_queue_readonly` | 3 | MCP implementation queue read-only |
79
- | `official_queue` | 7 | Full official mirror queue (read + write) |
80
- | `official_queue_readonly` | 2 | Official mirror queue read-only |
90
+ | Group | Tools | Description |
91
+ | ----------------------------- | ----- | -------------------------------------------- |
92
+ | `newsletter` | 6 | Full newsletter management (read + write) |
93
+ | `newsletter_readonly` | 3 | Newsletter read-only (get posts, authors) |
94
+ | `server_queue` | 5 | Full MCP implementation queue (read + write) |
95
+ | `server_queue_readonly` | 3 | MCP implementation queue read-only |
96
+ | `official_queue` | 7 | Full official mirror queue (read + write) |
97
+ | `official_queue_readonly` | 2 | Official mirror queue read-only |
98
+ | `unofficial_mirrors` | 5 | Full unofficial mirrors CRUD (read + write) |
99
+ | `unofficial_mirrors_readonly` | 2 | Unofficial mirrors read-only |
100
+ | `official_mirrors` | 2 | Official mirrors REST API (read-only) |
101
+ | `official_mirrors_readonly` | 2 | Official mirrors read-only (alias) |
102
+ | `tenants` | 2 | Tenants REST API (read-only) |
103
+ | `tenants_readonly` | 2 | Tenants read-only (alias) |
104
+ | `mcp_jsons` | 5 | Full MCP JSON configurations (read + write) |
105
+ | `mcp_jsons_readonly` | 2 | MCP JSON configurations read-only |
106
+ | `mcp_servers` | 3 | Full MCP servers management (read + write) |
107
+ | `mcp_servers_readonly` | 2 | MCP servers read-only (list, get) |
81
108
 
82
109
  ### Tools by Group
83
110
 
@@ -90,12 +117,25 @@ This server organizes tools into groups that can be selectively enabled or disab
90
117
  - **official_queue** / **official_queue_readonly**:
91
118
  - Read-only: `get_official_mirror_queue_items`, `get_official_mirror_queue_item`
92
119
  - Write: `approve_official_mirror_queue_item`, `approve_mirror_no_modify`, `reject_official_mirror_queue_item`, `add_official_mirror_to_regular_queue`, `unlink_official_mirror_queue_item`
120
+ - **unofficial_mirrors** / **unofficial_mirrors_readonly**:
121
+ - Read-only: `get_unofficial_mirrors`, `get_unofficial_mirror`
122
+ - Write: `create_unofficial_mirror`, `update_unofficial_mirror`, `delete_unofficial_mirror`
123
+ - **official_mirrors** / **official_mirrors_readonly**:
124
+ - Read-only: `get_official_mirrors`, `get_official_mirror`
125
+ - **tenants** / **tenants_readonly**:
126
+ - Read-only: `get_tenants`, `get_tenant`
127
+ - **mcp_jsons** / **mcp_jsons_readonly**:
128
+ - Read-only: `get_mcp_jsons`, `get_mcp_json`
129
+ - Write: `create_mcp_json`, `update_mcp_json`, `delete_mcp_json`
130
+ - **mcp_servers** / **mcp_servers_readonly**:
131
+ - Read-only: `list_mcp_servers`, `get_mcp_server`
132
+ - Write: `update_mcp_server`
93
133
 
94
134
  ## Environment Variables
95
135
 
96
- | Variable | Description | Default |
97
- | ------------- | ------------------------------------------- | ---------------------------------------------------------- |
98
- | `TOOL_GROUPS` | Comma-separated list of enabled tool groups | `newsletter,server_queue,official_queue` (all base groups) |
136
+ | Variable | Description | Default |
137
+ | ------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
138
+ | `TOOL_GROUPS` | Comma-separated list of enabled tool groups | `newsletter,server_queue,official_queue,unofficial_mirrors,official_mirrors,tenants,mcp_jsons,mcp_servers` (all base groups) |
99
139
 
100
140
  ## Examples
101
141
 
@@ -120,7 +160,7 @@ TOOL_GROUPS=server_queue_readonly
120
160
  Enable all groups with read-only access:
121
161
 
122
162
  ```bash
123
- TOOL_GROUPS=newsletter_readonly,server_queue_readonly,official_queue_readonly
163
+ TOOL_GROUPS=newsletter_readonly,server_queue_readonly,official_queue_readonly,unofficial_mirrors_readonly,official_mirrors_readonly,tenants_readonly,mcp_jsons_readonly,mcp_servers_readonly
124
164
  ```
125
165
 
126
166
  Mix full and read-only access per group:
@@ -146,6 +186,10 @@ TOOL_GROUPS=newsletter,server_queue_readonly
146
186
  - Use the `canonical` array parameter in `save_mcp_implementation` to set canonical URLs with scope (domain, subdomain, subfolder, or url)
147
187
  - Remote endpoints allow specifying how MCP servers can be accessed (direct URL, setup URL, authentication method, cost, etc.)
148
188
  - When updating existing remotes, include the remote `id` (number from `get_draft_mcp_implementations`) in the remote object
189
+ - Use `list_mcp_servers` to browse MCP servers with filtering by status (draft/live/archived) and classification (official/community)
190
+ - Use `get_mcp_server` to get a unified view of all server data including provider, source code, canonicals, remotes, and tags
191
+ - Use `update_mcp_server` to update any admin UI field: name, description, provider, source code, package info, tags, canonicals, remotes, etc.
192
+ - The `mcp_servers` tools abstract away the MCPImplementation → MCPServer data model complexity
149
193
 
150
194
  # Examples
151
195
 
@@ -252,7 +296,7 @@ Add to your Claude Desktop configuration:
252
296
  "args": ["/path/to/pulsemcp-cms-admin/local/build/index.js"],
253
297
  "env": {
254
298
  "PULSEMCP_ADMIN_API_KEY": "your-api-key-here",
255
- "TOOL_GROUPS": "newsletter,server_queue,official_queue"
299
+ "TOOL_GROUPS": "newsletter,server_queue,official_queue,unofficial_mirrors,official_mirrors,tenants,mcp_jsons,mcp_servers"
256
300
  }
257
301
  }
258
302
  }
@@ -269,7 +313,7 @@ For read-only access:
269
313
  "args": ["/path/to/pulsemcp-cms-admin/local/build/index.js"],
270
314
  "env": {
271
315
  "PULSEMCP_ADMIN_API_KEY": "your-api-key-here",
272
- "TOOL_GROUPS": "newsletter_readonly,server_queue_readonly,official_queue_readonly"
316
+ "TOOL_GROUPS": "newsletter_readonly,server_queue_readonly,official_queue_readonly,unofficial_mirrors_readonly,official_mirrors_readonly,tenants_readonly,mcp_jsons_readonly,mcp_servers_readonly"
273
317
  }
274
318
  }
275
319
  }
@@ -0,0 +1,46 @@
1
+ export async function createMcpJson(apiKey, baseUrl, params) {
2
+ const url = new URL('/api/mcp_jsons', baseUrl);
3
+ const body = {
4
+ mcp_servers_unofficial_mirror_id: params.mcp_servers_unofficial_mirror_id,
5
+ title: params.title,
6
+ value: typeof params.value === 'string' ? params.value : JSON.stringify(params.value),
7
+ };
8
+ if (params.description !== undefined) {
9
+ body.description = params.description;
10
+ }
11
+ const response = await fetch(url.toString(), {
12
+ method: 'POST',
13
+ headers: {
14
+ 'X-API-Key': apiKey,
15
+ 'Content-Type': 'application/json',
16
+ Accept: 'application/json',
17
+ },
18
+ body: JSON.stringify(body),
19
+ });
20
+ if (!response.ok) {
21
+ if (response.status === 401) {
22
+ throw new Error('Invalid API key');
23
+ }
24
+ if (response.status === 403) {
25
+ throw new Error('User lacks write privileges');
26
+ }
27
+ if (response.status === 422) {
28
+ const errorData = (await response.json());
29
+ throw new Error(`Validation failed: ${errorData.errors?.join(', ') || 'Unknown error'}`);
30
+ }
31
+ throw new Error(`Failed to create MCP JSON: ${response.status} ${response.statusText}`);
32
+ }
33
+ const mcpJson = (await response.json());
34
+ return {
35
+ id: mcpJson.id,
36
+ mcp_servers_unofficial_mirror_id: mcpJson.mcp_servers_unofficial_mirror_id,
37
+ unofficial_mirror_name: mcpJson.unofficial_mirror_name,
38
+ unofficial_mirror_version: mcpJson.unofficial_mirror_version,
39
+ title: mcpJson.title,
40
+ description: mcpJson.description,
41
+ value: mcpJson.value,
42
+ server_key: mcpJson.server_key,
43
+ created_at: mcpJson.created_at,
44
+ updated_at: mcpJson.updated_at,
45
+ };
46
+ }
@@ -0,0 +1,55 @@
1
+ export async function createUnofficialMirror(apiKey, baseUrl, params) {
2
+ const url = new URL('/api/unofficial_mirrors', baseUrl);
3
+ const body = {
4
+ name: params.name,
5
+ version: params.version,
6
+ jsonb_data: typeof params.jsonb_data === 'string' ? params.jsonb_data : JSON.stringify(params.jsonb_data),
7
+ };
8
+ if (params.mcp_server_id !== undefined) {
9
+ body.mcp_server_id = params.mcp_server_id;
10
+ }
11
+ if (params.previous_name !== undefined) {
12
+ body.previous_name = params.previous_name;
13
+ }
14
+ if (params.next_name !== undefined) {
15
+ body.next_name = params.next_name;
16
+ }
17
+ const response = await fetch(url.toString(), {
18
+ method: 'POST',
19
+ headers: {
20
+ 'X-API-Key': apiKey,
21
+ 'Content-Type': 'application/json',
22
+ Accept: 'application/json',
23
+ },
24
+ body: JSON.stringify(body),
25
+ });
26
+ if (!response.ok) {
27
+ if (response.status === 401) {
28
+ throw new Error('Invalid API key');
29
+ }
30
+ if (response.status === 403) {
31
+ throw new Error('User lacks write privileges');
32
+ }
33
+ if (response.status === 422) {
34
+ const errorData = (await response.json());
35
+ throw new Error(`Validation failed: ${errorData.errors?.join(', ') || 'Unknown error'}`);
36
+ }
37
+ throw new Error(`Failed to create unofficial mirror: ${response.status} ${response.statusText}`);
38
+ }
39
+ const mirror = (await response.json());
40
+ return {
41
+ id: mirror.id,
42
+ name: mirror.name,
43
+ version: mirror.version,
44
+ jsonb_data: mirror.jsonb_data,
45
+ datetime_ingested: mirror.datetime_ingested,
46
+ mcp_server_id: mirror.mcp_server_id,
47
+ mcp_server_slug: mirror.mcp_server_slug,
48
+ previous_name: mirror.previous_name,
49
+ next_name: mirror.next_name,
50
+ proctor_results_count: mirror.proctor_results_count,
51
+ mcp_jsons_count: mirror.mcp_jsons_count,
52
+ created_at: mirror.created_at,
53
+ updated_at: mirror.updated_at,
54
+ };
55
+ }
@@ -0,0 +1,24 @@
1
+ export async function deleteMcpJson(apiKey, baseUrl, id) {
2
+ const url = new URL(`/api/mcp_jsons/${id}`, baseUrl);
3
+ const response = await fetch(url.toString(), {
4
+ method: 'DELETE',
5
+ headers: {
6
+ 'X-API-Key': apiKey,
7
+ Accept: 'application/json',
8
+ },
9
+ });
10
+ if (!response.ok) {
11
+ if (response.status === 401) {
12
+ throw new Error('Invalid API key');
13
+ }
14
+ if (response.status === 403) {
15
+ throw new Error('User lacks write privileges');
16
+ }
17
+ if (response.status === 404) {
18
+ throw new Error(`MCP JSON with ID ${id} not found`);
19
+ }
20
+ throw new Error(`Failed to delete MCP JSON: ${response.status} ${response.statusText}`);
21
+ }
22
+ const data = (await response.json());
23
+ return data;
24
+ }
@@ -0,0 +1,24 @@
1
+ export async function deleteUnofficialMirror(apiKey, baseUrl, id) {
2
+ const url = new URL(`/api/unofficial_mirrors/${id}`, baseUrl);
3
+ const response = await fetch(url.toString(), {
4
+ method: 'DELETE',
5
+ headers: {
6
+ 'X-API-Key': apiKey,
7
+ Accept: 'application/json',
8
+ },
9
+ });
10
+ if (!response.ok) {
11
+ if (response.status === 401) {
12
+ throw new Error('Invalid API key');
13
+ }
14
+ if (response.status === 403) {
15
+ throw new Error('User lacks write privileges');
16
+ }
17
+ if (response.status === 404) {
18
+ throw new Error(`Unofficial mirror with ID ${id} not found`);
19
+ }
20
+ throw new Error(`Failed to delete unofficial mirror: ${response.status} ${response.statusText}`);
21
+ }
22
+ const data = (await response.json());
23
+ return data;
24
+ }
@@ -0,0 +1,35 @@
1
+ export async function getMcpJson(apiKey, baseUrl, id) {
2
+ const url = new URL(`/api/mcp_jsons/${id}`, baseUrl);
3
+ const response = await fetch(url.toString(), {
4
+ method: 'GET',
5
+ headers: {
6
+ 'X-API-Key': apiKey,
7
+ Accept: 'application/json',
8
+ },
9
+ });
10
+ if (!response.ok) {
11
+ if (response.status === 401) {
12
+ throw new Error('Invalid API key');
13
+ }
14
+ if (response.status === 403) {
15
+ throw new Error('User lacks admin privileges');
16
+ }
17
+ if (response.status === 404) {
18
+ throw new Error(`MCP JSON with ID ${id} not found`);
19
+ }
20
+ throw new Error(`Failed to fetch MCP JSON: ${response.status} ${response.statusText}`);
21
+ }
22
+ const mcpJson = (await response.json());
23
+ return {
24
+ id: mcpJson.id,
25
+ mcp_servers_unofficial_mirror_id: mcpJson.mcp_servers_unofficial_mirror_id,
26
+ unofficial_mirror_name: mcpJson.unofficial_mirror_name,
27
+ unofficial_mirror_version: mcpJson.unofficial_mirror_version,
28
+ title: mcpJson.title,
29
+ description: mcpJson.description,
30
+ value: mcpJson.value,
31
+ server_key: mcpJson.server_key,
32
+ created_at: mcpJson.created_at,
33
+ updated_at: mcpJson.updated_at,
34
+ };
35
+ }
@@ -0,0 +1,56 @@
1
+ function mapMcpJson(mcpJson) {
2
+ return {
3
+ id: mcpJson.id,
4
+ mcp_servers_unofficial_mirror_id: mcpJson.mcp_servers_unofficial_mirror_id,
5
+ unofficial_mirror_name: mcpJson.unofficial_mirror_name,
6
+ unofficial_mirror_version: mcpJson.unofficial_mirror_version,
7
+ title: mcpJson.title,
8
+ description: mcpJson.description,
9
+ value: mcpJson.value,
10
+ server_key: mcpJson.server_key,
11
+ created_at: mcpJson.created_at,
12
+ updated_at: mcpJson.updated_at,
13
+ };
14
+ }
15
+ export async function getMcpJsons(apiKey, baseUrl, params) {
16
+ const url = new URL('/api/mcp_jsons', baseUrl);
17
+ if (params?.unofficial_mirror_id) {
18
+ url.searchParams.append('unofficial_mirror_id', params.unofficial_mirror_id.toString());
19
+ }
20
+ if (params?.q) {
21
+ url.searchParams.append('q', params.q);
22
+ }
23
+ if (params?.limit) {
24
+ url.searchParams.append('limit', params.limit.toString());
25
+ }
26
+ if (params?.offset) {
27
+ url.searchParams.append('offset', params.offset.toString());
28
+ }
29
+ const response = await fetch(url.toString(), {
30
+ method: 'GET',
31
+ headers: {
32
+ 'X-API-Key': apiKey,
33
+ Accept: 'application/json',
34
+ },
35
+ });
36
+ if (!response.ok) {
37
+ if (response.status === 401) {
38
+ throw new Error('Invalid API key');
39
+ }
40
+ if (response.status === 403) {
41
+ throw new Error('User lacks admin privileges');
42
+ }
43
+ throw new Error(`Failed to fetch MCP JSONs: ${response.status} ${response.statusText}`);
44
+ }
45
+ const data = (await response.json());
46
+ return {
47
+ mcp_jsons: data.data.map(mapMcpJson),
48
+ pagination: {
49
+ current_page: data.meta.current_page,
50
+ total_pages: data.meta.total_pages,
51
+ total_count: data.meta.total_count,
52
+ has_next: data.meta.has_next,
53
+ limit: data.meta.limit,
54
+ },
55
+ };
56
+ }
@@ -0,0 +1,39 @@
1
+ export async function getOfficialMirror(apiKey, baseUrl, id) {
2
+ const url = new URL(`/api/official_mirrors/${id}`, baseUrl);
3
+ const response = await fetch(url.toString(), {
4
+ method: 'GET',
5
+ headers: {
6
+ 'X-API-Key': apiKey,
7
+ Accept: 'application/json',
8
+ },
9
+ });
10
+ if (!response.ok) {
11
+ if (response.status === 401) {
12
+ throw new Error('Invalid API key');
13
+ }
14
+ if (response.status === 403) {
15
+ throw new Error('User lacks admin privileges');
16
+ }
17
+ if (response.status === 404) {
18
+ throw new Error(`Official mirror with ID ${id} not found`);
19
+ }
20
+ throw new Error(`Failed to fetch official mirror: ${response.status} ${response.statusText}`);
21
+ }
22
+ const mirror = (await response.json());
23
+ return {
24
+ id: mirror.id,
25
+ name: mirror.name,
26
+ version: mirror.version,
27
+ official_version_id: mirror.official_version_id,
28
+ jsonb_data: mirror.jsonb_data,
29
+ datetime_ingested: mirror.datetime_ingested,
30
+ mcp_server_id: mirror.mcp_server_id,
31
+ mcp_server_slug: mirror.mcp_server_slug,
32
+ processed: mirror.processed,
33
+ processing_failure_reason: mirror.processing_failure_reason,
34
+ queue_id: mirror.queue_id,
35
+ queue_status: mirror.queue_status,
36
+ created_at: mirror.created_at,
37
+ updated_at: mirror.updated_at,
38
+ };
39
+ }
@@ -0,0 +1,66 @@
1
+ function mapMirror(mirror) {
2
+ return {
3
+ id: mirror.id,
4
+ name: mirror.name,
5
+ version: mirror.version,
6
+ official_version_id: mirror.official_version_id,
7
+ jsonb_data: mirror.jsonb_data,
8
+ datetime_ingested: mirror.datetime_ingested,
9
+ mcp_server_id: mirror.mcp_server_id,
10
+ mcp_server_slug: mirror.mcp_server_slug,
11
+ processed: mirror.processed,
12
+ processing_failure_reason: mirror.processing_failure_reason,
13
+ queue_id: mirror.queue_id,
14
+ queue_status: mirror.queue_status,
15
+ created_at: mirror.created_at,
16
+ updated_at: mirror.updated_at,
17
+ };
18
+ }
19
+ export async function getOfficialMirrors(apiKey, baseUrl, params) {
20
+ const url = new URL('/api/official_mirrors', baseUrl);
21
+ if (params?.q) {
22
+ url.searchParams.append('q', params.q);
23
+ }
24
+ if (params?.mcp_server_id) {
25
+ url.searchParams.append('mcp_server_id', params.mcp_server_id.toString());
26
+ }
27
+ if (params?.status) {
28
+ url.searchParams.append('status', params.status);
29
+ }
30
+ if (params?.processed !== undefined) {
31
+ url.searchParams.append('processed', params.processed.toString());
32
+ }
33
+ if (params?.limit) {
34
+ url.searchParams.append('limit', params.limit.toString());
35
+ }
36
+ if (params?.offset) {
37
+ url.searchParams.append('offset', params.offset.toString());
38
+ }
39
+ const response = await fetch(url.toString(), {
40
+ method: 'GET',
41
+ headers: {
42
+ 'X-API-Key': apiKey,
43
+ Accept: 'application/json',
44
+ },
45
+ });
46
+ if (!response.ok) {
47
+ if (response.status === 401) {
48
+ throw new Error('Invalid API key');
49
+ }
50
+ if (response.status === 403) {
51
+ throw new Error('User lacks admin privileges');
52
+ }
53
+ throw new Error(`Failed to fetch official mirrors: ${response.status} ${response.statusText}`);
54
+ }
55
+ const data = (await response.json());
56
+ return {
57
+ mirrors: data.data.map(mapMirror),
58
+ pagination: {
59
+ current_page: data.meta.current_page,
60
+ total_pages: data.meta.total_pages,
61
+ total_count: data.meta.total_count,
62
+ has_next: data.meta.has_next,
63
+ limit: data.meta.limit,
64
+ },
65
+ };
66
+ }
@@ -0,0 +1,31 @@
1
+ export async function getTenant(apiKey, baseUrl, idOrSlug) {
2
+ const url = new URL(`/api/tenants/${idOrSlug}`, baseUrl);
3
+ const response = await fetch(url.toString(), {
4
+ method: 'GET',
5
+ headers: {
6
+ 'X-API-Key': apiKey,
7
+ Accept: 'application/json',
8
+ },
9
+ });
10
+ if (!response.ok) {
11
+ if (response.status === 401) {
12
+ throw new Error('Invalid API key');
13
+ }
14
+ if (response.status === 403) {
15
+ throw new Error('User lacks admin privileges');
16
+ }
17
+ if (response.status === 404) {
18
+ throw new Error(`Tenant with ID/slug ${idOrSlug} not found`);
19
+ }
20
+ throw new Error(`Failed to fetch tenant: ${response.status} ${response.statusText}`);
21
+ }
22
+ const tenant = (await response.json());
23
+ return {
24
+ id: tenant.id,
25
+ slug: tenant.slug,
26
+ is_admin: tenant.is_admin,
27
+ enrichments: tenant.enrichments,
28
+ created_at: tenant.created_at,
29
+ updated_at: tenant.updated_at,
30
+ };
31
+ }
@@ -0,0 +1,52 @@
1
+ function mapTenant(tenant) {
2
+ return {
3
+ id: tenant.id,
4
+ slug: tenant.slug,
5
+ is_admin: tenant.is_admin,
6
+ enrichments: tenant.enrichments,
7
+ created_at: tenant.created_at,
8
+ updated_at: tenant.updated_at,
9
+ };
10
+ }
11
+ export async function getTenants(apiKey, baseUrl, params) {
12
+ const url = new URL('/api/tenants', baseUrl);
13
+ if (params?.q) {
14
+ url.searchParams.append('q', params.q);
15
+ }
16
+ if (params?.is_admin !== undefined) {
17
+ url.searchParams.append('is_admin', params.is_admin.toString());
18
+ }
19
+ if (params?.limit) {
20
+ url.searchParams.append('limit', params.limit.toString());
21
+ }
22
+ if (params?.offset) {
23
+ url.searchParams.append('offset', params.offset.toString());
24
+ }
25
+ const response = await fetch(url.toString(), {
26
+ method: 'GET',
27
+ headers: {
28
+ 'X-API-Key': apiKey,
29
+ Accept: 'application/json',
30
+ },
31
+ });
32
+ if (!response.ok) {
33
+ if (response.status === 401) {
34
+ throw new Error('Invalid API key');
35
+ }
36
+ if (response.status === 403) {
37
+ throw new Error('User lacks admin privileges');
38
+ }
39
+ throw new Error(`Failed to fetch tenants: ${response.status} ${response.statusText}`);
40
+ }
41
+ const data = (await response.json());
42
+ return {
43
+ tenants: data.data.map(mapTenant),
44
+ pagination: {
45
+ current_page: data.meta.current_page,
46
+ total_pages: data.meta.total_pages,
47
+ total_count: data.meta.total_count,
48
+ has_next: data.meta.has_next,
49
+ limit: data.meta.limit,
50
+ },
51
+ };
52
+ }