plex-mcp 0.1.0 → 0.2.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.
@@ -0,0 +1,11 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "npm" # See documentation for possible values
9
+ directory: "/" # Location of package manifests
10
+ schedule:
11
+ interval: "daily"
package/README.md CHANGED
@@ -8,6 +8,8 @@ A Model Context Protocol (MCP) server for searching Plex media libraries using C
8
8
  - Filter by content type
9
9
  - Configurable result limits
10
10
  - Rich formatted results with metadata
11
+ - **Direct Plex authentication with OAuth flow**
12
+ - Support for both static tokens and interactive authentication
11
13
 
12
14
  ## Setup
13
15
 
@@ -16,19 +18,22 @@ A Model Context Protocol (MCP) server for searching Plex media libraries using C
16
18
  npm install
17
19
  ```
18
20
 
19
- 2. Configure your Plex connection:
20
- - Copy `.env.example` to `.env`
21
+ 2. Configure your Plex connection (two options):
22
+
23
+ **Option A: Interactive Authentication (Recommended)**
24
+ - Set your Plex server URL:
25
+ ```
26
+ PLEX_URL=http://your-plex-server:32400
27
+ ```
28
+ - Use the `authenticate_plex` tool for OAuth login (see Authentication section below)
29
+
30
+ **Option B: Static Token**
21
31
  - Set your Plex server URL and token:
22
32
  ```
23
33
  PLEX_URL=http://your-plex-server:32400
24
34
  PLEX_TOKEN=your_plex_token
25
35
  ```
26
-
27
- 3. Get your Plex token:
28
- - Log into your Plex account
29
- - Go to Settings > Account > Privacy
30
- - Click "Show" next to "Plex Pass Subscription"
31
- - Your token will be displayed
36
+ - Get your Plex token by visiting [Plex Token](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/)
32
37
 
33
38
  ## Claude Desktop Configuration
34
39
 
@@ -113,9 +118,76 @@ Run the MCP server standalone:
113
118
  node index.js
114
119
  ```
115
120
 
121
+ ## Authentication
122
+
123
+ The Plex MCP server supports two authentication methods:
124
+
125
+ ### 1. Interactive OAuth Authentication (Recommended)
126
+
127
+ Use the built-in OAuth flow for secure, interactive authentication:
128
+
129
+ 1. **Start Authentication:**
130
+ ```
131
+ Use the authenticate_plex tool
132
+ ```
133
+ This will provide you with a Plex login URL and pin ID.
134
+
135
+ 2. **Complete Login:**
136
+ - Open the provided URL in your browser
137
+ - Sign into your Plex account
138
+ - Grant access to the MCP application
139
+
140
+ 3. **Check Authentication Status:**
141
+ ```
142
+ Use the check_auth_status tool
143
+ ```
144
+ This confirms authentication completion and stores your token.
145
+
146
+ 4. **Clear Authentication (Optional):**
147
+ ```
148
+ Use the clear_auth tool
149
+ ```
150
+ This removes stored credentials if needed.
151
+
152
+ ### 2. Static Token Authentication
153
+
154
+ For automated setups or if you prefer manual token management:
155
+
156
+ 1. Obtain your Plex token from [Plex Support](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/)
157
+ 2. Set the `PLEX_TOKEN` environment variable
158
+ 3. All tools will automatically use this token
159
+
160
+ **Note:** The OAuth method takes precedence - if both are available, static tokens are used as fallback.
161
+
116
162
  ## MCP Tools
117
163
 
118
- ### search_plex
164
+ ### Authentication Tools
165
+
166
+ #### authenticate_plex
167
+ Start the Plex OAuth authentication flow.
168
+
169
+ **Parameters:** None
170
+
171
+ **Returns:** Login URL and pin ID for browser authentication.
172
+
173
+ #### check_auth_status
174
+ Check if OAuth authentication is complete and retrieve the token.
175
+
176
+ **Parameters:**
177
+ - `pin_id` (string, optional): Specific pin ID to check
178
+
179
+ **Returns:** Authentication status and success confirmation.
180
+
181
+ #### clear_auth
182
+ Clear stored authentication credentials.
183
+
184
+ **Parameters:** None
185
+
186
+ **Returns:** Confirmation of credential removal.
187
+
188
+ ### Content Tools
189
+
190
+ #### search_plex
119
191
 
120
192
  Search for content in your Plex libraries.
121
193
 
package/index.js CHANGED
@@ -7,6 +7,84 @@ const {
7
7
  ListToolsRequestSchema,
8
8
  } = require("@modelcontextprotocol/sdk/types.js");
9
9
  const axios = require('axios');
10
+ const { PlexOauth } = require('plex-oauth');
11
+
12
+ class PlexAuthManager {
13
+ constructor() {
14
+ this.authToken = null;
15
+ this.plexOauth = null;
16
+ this.currentPinId = null;
17
+ }
18
+
19
+ async getAuthToken() {
20
+ // Try static token first
21
+ const staticToken = process.env.PLEX_TOKEN;
22
+ if (staticToken) {
23
+ return staticToken;
24
+ }
25
+
26
+ // Return stored OAuth token if available
27
+ if (this.authToken) {
28
+ return this.authToken;
29
+ }
30
+
31
+ throw new Error('No authentication token available. Please authenticate first using the authenticate_plex tool or set PLEX_TOKEN environment variable.');
32
+ }
33
+
34
+ initializeOAuth() {
35
+ if (this.plexOauth) {
36
+ return this.plexOauth;
37
+ }
38
+
39
+ const clientInfo = {
40
+ clientIdentifier: process.env.PLEX_CLIENT_ID || 'plex-mcp-client',
41
+ product: process.env.PLEX_PRODUCT || 'Plex MCP Server',
42
+ device: process.env.PLEX_DEVICE || 'MCP Server',
43
+ version: process.env.PLEX_VERSION || '1.0.0',
44
+ forwardUrl: process.env.PLEX_REDIRECT_URL || 'https://app.plex.tv/auth#!',
45
+ platform: process.env.PLEX_PLATFORM || 'Web'
46
+ };
47
+
48
+ this.plexOauth = new PlexOauth(clientInfo);
49
+ return this.plexOauth;
50
+ }
51
+
52
+ async requestAuthUrl() {
53
+ const oauth = this.initializeOAuth();
54
+ try {
55
+ const [hostedUILink, pinId] = await oauth.requestHostedLoginURL();
56
+ this.currentPinId = pinId;
57
+ return { loginUrl: hostedUILink, pinId };
58
+ } catch (error) {
59
+ throw new Error(`Failed to request authentication URL: ${error.message}`);
60
+ }
61
+ }
62
+
63
+ async checkAuthToken(pinId = null) {
64
+ const oauth = this.initializeOAuth();
65
+ const pin = pinId || this.currentPinId;
66
+
67
+ if (!pin) {
68
+ throw new Error('No pin ID available. Please request authentication first.');
69
+ }
70
+
71
+ try {
72
+ const authToken = await oauth.checkForAuthToken(pin);
73
+ if (authToken) {
74
+ this.authToken = authToken;
75
+ return authToken;
76
+ }
77
+ return null;
78
+ } catch (error) {
79
+ throw new Error(`Failed to check authentication token: ${error.message}`);
80
+ }
81
+ }
82
+
83
+ clearAuth() {
84
+ this.authToken = null;
85
+ this.currentPinId = null;
86
+ }
87
+ }
10
88
 
11
89
  class PlexMCPServer {
12
90
  constructor() {
@@ -22,6 +100,7 @@ class PlexMCPServer {
22
100
  }
23
101
  );
24
102
 
103
+ this.authManager = new PlexAuthManager();
25
104
  this.setupToolHandlers();
26
105
  }
27
106
 
@@ -623,6 +702,38 @@ class PlexMCPServer {
623
702
  required: [],
624
703
  },
625
704
  },
705
+ {
706
+ name: "authenticate_plex",
707
+ description: "Initiate Plex OAuth authentication flow to get user login URL",
708
+ inputSchema: {
709
+ type: "object",
710
+ properties: {},
711
+ required: [],
712
+ },
713
+ },
714
+ {
715
+ name: "check_auth_status",
716
+ description: "Check if Plex authentication is complete and retrieve the auth token",
717
+ inputSchema: {
718
+ type: "object",
719
+ properties: {
720
+ pin_id: {
721
+ type: "string",
722
+ description: "Optional pin ID to check. If not provided, uses the last requested pin.",
723
+ },
724
+ },
725
+ required: [],
726
+ },
727
+ },
728
+ {
729
+ name: "clear_auth",
730
+ description: "Clear stored authentication credentials",
731
+ inputSchema: {
732
+ type: "object",
733
+ properties: {},
734
+ required: [],
735
+ },
736
+ },
626
737
  ],
627
738
  };
628
739
  });
@@ -666,12 +777,132 @@ class PlexMCPServer {
666
777
  return await this.handleGetLibraryStats(request.params.arguments);
667
778
  case "get_listening_stats":
668
779
  return await this.handleGetListeningStats(request.params.arguments);
780
+ case "authenticate_plex":
781
+ return await this.handleAuthenticatePlex(request.params.arguments);
782
+ case "check_auth_status":
783
+ return await this.handleCheckAuthStatus(request.params.arguments);
784
+ case "clear_auth":
785
+ return await this.handleClearAuth(request.params.arguments);
669
786
  default:
670
787
  throw new Error(`Unknown tool: ${request.params.name}`);
671
788
  }
672
789
  });
673
790
  }
674
791
 
792
+ async handleAuthenticatePlex(args) {
793
+ try {
794
+ const { loginUrl, pinId } = await this.authManager.requestAuthUrl();
795
+
796
+ return {
797
+ content: [
798
+ {
799
+ type: "text",
800
+ text: `Plex Authentication Started
801
+
802
+ **Next Steps:**
803
+ 1. Open this URL in your browser: ${loginUrl}
804
+ 2. Sign into your Plex account
805
+ 3. After signing in, run the check_auth_status tool to complete authentication
806
+
807
+ **Pin ID:** ${pinId}
808
+
809
+ Note: Keep this pin ID if you want to check auth status manually later.`
810
+ }
811
+ ]
812
+ };
813
+ } catch (error) {
814
+ return {
815
+ content: [
816
+ {
817
+ type: "text",
818
+ text: `❌ Authentication Error: ${error.message}`
819
+ }
820
+ ],
821
+ isError: true
822
+ };
823
+ }
824
+ }
825
+
826
+ async handleCheckAuthStatus(args) {
827
+ const { pin_id } = args;
828
+
829
+ try {
830
+ const authToken = await this.authManager.checkAuthToken(pin_id);
831
+
832
+ if (authToken) {
833
+ return {
834
+ content: [
835
+ {
836
+ type: "text",
837
+ text: `✅ Plex Authentication Successful!
838
+
839
+ Your authentication token has been stored and will be used for all Plex API requests. You can now use all Plex tools without needing the PLEX_TOKEN environment variable.
840
+
841
+ **Note:** This token is stored only for this session. For persistent authentication, consider setting the PLEX_TOKEN environment variable.`
842
+ }
843
+ ]
844
+ };
845
+ } else {
846
+ return {
847
+ content: [
848
+ {
849
+ type: "text",
850
+ text: `⏳ Authentication Pending
851
+
852
+ The user has not yet completed the authentication process. Please:
853
+
854
+ 1. Make sure you've visited the login URL from the authenticate_plex tool
855
+ 2. Sign into your Plex account in the browser
856
+ 3. Try checking the auth status again in a few moments
857
+
858
+ You can run check_auth_status again to check if authentication is complete.`
859
+ }
860
+ ]
861
+ };
862
+ }
863
+ } catch (error) {
864
+ return {
865
+ content: [
866
+ {
867
+ type: "text",
868
+ text: `❌ Auth Status Check Error: ${error.message}`
869
+ }
870
+ ],
871
+ isError: true
872
+ };
873
+ }
874
+ }
875
+
876
+ async handleClearAuth(args) {
877
+ try {
878
+ this.authManager.clearAuth();
879
+
880
+ return {
881
+ content: [
882
+ {
883
+ type: "text",
884
+ text: `🔄 Authentication Cleared
885
+
886
+ All stored authentication credentials have been cleared. To use Plex tools again, you'll need to either:
887
+
888
+ 1. Set the PLEX_TOKEN environment variable, or
889
+ 2. Run the authenticate_plex tool to sign in again`
890
+ }
891
+ ]
892
+ };
893
+ } catch (error) {
894
+ return {
895
+ content: [
896
+ {
897
+ type: "text",
898
+ text: `❌ Clear Auth Error: ${error.message}`
899
+ }
900
+ ],
901
+ isError: true
902
+ };
903
+ }
904
+ }
905
+
675
906
  async handlePlexSearch(args) {
676
907
  const {
677
908
  query,
@@ -706,11 +937,7 @@ class PlexMCPServer {
706
937
 
707
938
  try {
708
939
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
709
- const plexToken = process.env.PLEX_TOKEN;
710
-
711
- if (!plexToken) {
712
- throw new Error('PLEX_TOKEN environment variable is required');
713
- }
940
+ const plexToken = await this.authManager.getAuthToken();
714
941
 
715
942
  const searchUrl = `${plexUrl}/search`;
716
943
  const params = {
@@ -891,11 +1118,7 @@ class PlexMCPServer {
891
1118
  async handleBrowseLibraries(args) {
892
1119
  try {
893
1120
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
894
- const plexToken = process.env.PLEX_TOKEN;
895
-
896
- if (!plexToken) {
897
- throw new Error('PLEX_TOKEN environment variable is required');
898
- }
1121
+ const plexToken = await this.authManager.getAuthToken();
899
1122
 
900
1123
  const librariesUrl = `${plexUrl}/library/sections`;
901
1124
  const params = {
@@ -1007,11 +1230,7 @@ class PlexMCPServer {
1007
1230
 
1008
1231
  try {
1009
1232
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1010
- const plexToken = process.env.PLEX_TOKEN;
1011
-
1012
- if (!plexToken) {
1013
- throw new Error('PLEX_TOKEN environment variable is required');
1014
- }
1233
+ const plexToken = await this.authManager.getAuthToken();
1015
1234
 
1016
1235
  const libraryUrl = `${plexUrl}/library/sections/${library_id}/all`;
1017
1236
  const params = {
@@ -1133,11 +1352,7 @@ class PlexMCPServer {
1133
1352
 
1134
1353
  try {
1135
1354
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1136
- const plexToken = process.env.PLEX_TOKEN;
1137
-
1138
- if (!plexToken) {
1139
- throw new Error('PLEX_TOKEN environment variable is required');
1140
- }
1355
+ const plexToken = await this.authManager.getAuthToken();
1141
1356
 
1142
1357
  let recentUrl;
1143
1358
  if (library_id) {
@@ -1233,11 +1448,7 @@ class PlexMCPServer {
1233
1448
 
1234
1449
  try {
1235
1450
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1236
- const plexToken = process.env.PLEX_TOKEN;
1237
-
1238
- if (!plexToken) {
1239
- throw new Error('PLEX_TOKEN environment variable is required');
1240
- }
1451
+ const plexToken = await this.authManager.getAuthToken();
1241
1452
 
1242
1453
  const historyUrl = `${plexUrl}/status/sessions/history/all`;
1243
1454
  const params = {
@@ -1357,11 +1568,7 @@ class PlexMCPServer {
1357
1568
 
1358
1569
  try {
1359
1570
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1360
- const plexToken = process.env.PLEX_TOKEN;
1361
-
1362
- if (!plexToken) {
1363
- throw new Error('PLEX_TOKEN environment variable is required');
1364
- }
1571
+ const plexToken = await this.authManager.getAuthToken();
1365
1572
 
1366
1573
  const onDeckUrl = `${plexUrl}/library/onDeck`;
1367
1574
  const params = {
@@ -1460,11 +1667,7 @@ class PlexMCPServer {
1460
1667
 
1461
1668
  try {
1462
1669
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1463
- const plexToken = process.env.PLEX_TOKEN;
1464
-
1465
- if (!plexToken) {
1466
- throw new Error('PLEX_TOKEN environment variable is required');
1467
- }
1670
+ const plexToken = await this.authManager.getAuthToken();
1468
1671
 
1469
1672
  const playlistsUrl = `${plexUrl}/playlists`;
1470
1673
  const params = {
@@ -1512,11 +1715,7 @@ class PlexMCPServer {
1512
1715
 
1513
1716
  try {
1514
1717
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1515
- const plexToken = process.env.PLEX_TOKEN;
1516
-
1517
- if (!plexToken) {
1518
- throw new Error('PLEX_TOKEN environment variable is required');
1519
- }
1718
+ const plexToken = await this.authManager.getAuthToken();
1520
1719
 
1521
1720
  // First get playlist info
1522
1721
  const playlistUrl = `${plexUrl}/playlists/${playlist_id}`;
@@ -1730,11 +1929,7 @@ class PlexMCPServer {
1730
1929
 
1731
1930
  try {
1732
1931
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1733
- const plexToken = process.env.PLEX_TOKEN;
1734
-
1735
- if (!plexToken) {
1736
- throw new Error('PLEX_TOKEN environment variable is required');
1737
- }
1932
+ const plexToken = await this.authManager.getAuthToken();
1738
1933
 
1739
1934
  // First get server info to get machine identifier
1740
1935
  const serverResponse = await axios.get(`${plexUrl}/`, {
@@ -1839,11 +2034,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
1839
2034
 
1840
2035
  try {
1841
2036
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
1842
- const plexToken = process.env.PLEX_TOKEN;
1843
-
1844
- if (!plexToken) {
1845
- throw new Error('PLEX_TOKEN environment variable is required');
1846
- }
2037
+ const plexToken = await this.authManager.getAuthToken();
1847
2038
 
1848
2039
  // Get playlist info before adding items
1849
2040
  const playlistInfoUrl = `${plexUrl}/playlists/${playlist_id}`;
@@ -2000,11 +2191,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
2000
2191
 
2001
2192
  try {
2002
2193
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
2003
- const plexToken = process.env.PLEX_TOKEN;
2004
-
2005
- if (!plexToken) {
2006
- throw new Error('PLEX_TOKEN environment variable is required');
2007
- }
2194
+ const plexToken = await this.authManager.getAuthToken();
2008
2195
 
2009
2196
  // Get playlist info before removing items
2010
2197
  const playlistInfoUrl = `${plexUrl}/playlists/${playlist_id}`;
@@ -2184,11 +2371,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
2184
2371
 
2185
2372
  try {
2186
2373
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
2187
- const plexToken = process.env.PLEX_TOKEN;
2188
-
2189
- if (!plexToken) {
2190
- throw new Error('PLEX_TOKEN environment variable is required');
2191
- }
2374
+ const plexToken = await this.authManager.getAuthToken();
2192
2375
 
2193
2376
  const deleteUrl = `${plexUrl}/playlists/${playlist_id}`;
2194
2377
  const params = {
@@ -2228,11 +2411,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
2228
2411
 
2229
2412
  try {
2230
2413
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
2231
- const plexToken = process.env.PLEX_TOKEN;
2232
-
2233
- if (!plexToken) {
2234
- throw new Error('PLEX_TOKEN environment variable is required');
2235
- }
2414
+ const plexToken = await this.authManager.getAuthToken();
2236
2415
 
2237
2416
  const statusResults = [];
2238
2417
 
@@ -2675,11 +2854,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
2675
2854
 
2676
2855
  try {
2677
2856
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
2678
- const plexToken = process.env.PLEX_TOKEN;
2679
-
2680
- if (!plexToken) {
2681
- throw new Error('PLEX_TOKEN environment variable is required');
2682
- }
2857
+ const plexToken = await this.authManager.getAuthToken();
2683
2858
 
2684
2859
  let collectionsUrl;
2685
2860
  if (library_id) {
@@ -2729,11 +2904,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
2729
2904
 
2730
2905
  try {
2731
2906
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
2732
- const plexToken = process.env.PLEX_TOKEN;
2733
-
2734
- if (!plexToken) {
2735
- throw new Error('PLEX_TOKEN environment variable is required');
2736
- }
2907
+ const plexToken = await this.authManager.getAuthToken();
2737
2908
 
2738
2909
  const collectionUrl = `${plexUrl}/library/collections/${collection_id}/children`;
2739
2910
  const params = {
@@ -2832,11 +3003,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
2832
3003
 
2833
3004
  try {
2834
3005
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
2835
- const plexToken = process.env.PLEX_TOKEN;
2836
-
2837
- if (!plexToken) {
2838
- throw new Error('PLEX_TOKEN environment variable is required');
2839
- }
3006
+ const plexToken = await this.authManager.getAuthToken();
2840
3007
 
2841
3008
  const mediaUrl = `${plexUrl}/library/metadata/${item_key}`;
2842
3009
  const params = {
@@ -3125,11 +3292,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
3125
3292
 
3126
3293
  try {
3127
3294
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
3128
- const plexToken = process.env.PLEX_TOKEN;
3129
-
3130
- if (!plexToken) {
3131
- throw new Error('PLEX_TOKEN environment variable is required');
3132
- }
3295
+ const plexToken = await this.authManager.getAuthToken();
3133
3296
 
3134
3297
  // Get library information first
3135
3298
  const librariesResponse = await axios.get(`${plexUrl}/library/sections`, {
@@ -3480,11 +3643,7 @@ You can try creating the playlist manually in Plex and then use other MCP tools
3480
3643
 
3481
3644
  try {
3482
3645
  const plexUrl = process.env.PLEX_URL || 'http://localhost:32400';
3483
- const plexToken = process.env.PLEX_TOKEN;
3484
-
3485
- if (!plexToken) {
3486
- throw new Error('PLEX_TOKEN environment variable is required');
3487
- }
3646
+ const plexToken = await this.authManager.getAuthToken();
3488
3647
 
3489
3648
  // Auto-detect music libraries if not specified
3490
3649
  let musicLibraries = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plex-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A Model Context Protocol (MCP) server that enables Claude to query and manage Plex media libraries.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -41,11 +41,12 @@
41
41
  "type": "commonjs",
42
42
  "dependencies": {
43
43
  "@modelcontextprotocol/sdk": "^1.12.1",
44
- "axios": "^1.9.0"
44
+ "axios": "^1.9.0",
45
+ "plex-oauth": "^1.2.2"
45
46
  },
46
47
  "devDependencies": {
47
- "jest": "^29.7.0",
48
- "@types/jest": "^29.5.8",
49
- "axios-mock-adapter": "^1.22.0"
48
+ "@types/jest": "^29.5.14",
49
+ "axios-mock-adapter": "^2.1.0",
50
+ "jest": "^29.7.0"
50
51
  }
51
52
  }