pythonanywhere-mcp-server 0.0.8__tar.gz → 0.0.9__tar.gz

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 (25) hide show
  1. {pythonanywhere_mcp_server-0.0.8/src/pythonanywhere_mcp_server.egg-info → pythonanywhere_mcp_server-0.0.9}/PKG-INFO +12 -8
  2. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/README.md +10 -6
  3. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/pyproject.toml +2 -2
  4. pythonanywhere_mcp_server-0.0.9/src/pythonanywhere_mcp_server/__init__.py +1 -0
  5. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/tools/file.py +21 -0
  6. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9/src/pythonanywhere_mcp_server.egg-info}/PKG-INFO +12 -8
  7. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server.egg-info/requires.txt +1 -1
  8. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/tests/test_file_tools.py +17 -0
  9. pythonanywhere_mcp_server-0.0.8/src/pythonanywhere_mcp_server/__init__.py +0 -1
  10. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/LICENSE +0 -0
  11. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/setup.cfg +0 -0
  12. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/__main__.py +0 -0
  13. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/server.py +0 -0
  14. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/tools/__init__.py +0 -0
  15. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/tools/schedule.py +0 -0
  16. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/tools/webapp.py +0 -0
  17. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server/tools/website.py +0 -0
  18. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server.egg-info/SOURCES.txt +0 -0
  19. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server.egg-info/dependency_links.txt +0 -0
  20. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server.egg-info/entry_points.txt +0 -0
  21. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/src/pythonanywhere_mcp_server.egg-info/top_level.txt +0 -0
  22. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/tests/test_schedule_tools.py +0 -0
  23. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/tests/test_server.py +0 -0
  24. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/tests/test_webapp_tools.py +0 -0
  25. {pythonanywhere_mcp_server-0.0.8 → pythonanywhere_mcp_server-0.0.9}/tests/test_website_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonanywhere-mcp-server
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: PythonAnywhere Model Context Protocol Server
5
5
  Author-email: PythonAnywhere Developers <developers@pythonanywhere.com>
6
6
  License-Expression: MIT
@@ -17,7 +17,7 @@ Classifier: Topic :: Utilities
17
17
  Requires-Python: >=3.13
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: pythonanywhere-core>=0.2.9
20
+ Requires-Dist: pythonanywhere-core>=0.3.0
21
21
  Requires-Dist: mcp[cli]
22
22
  Provides-Extra: test
23
23
  Requires-Dist: pytest; extra == "test"
@@ -60,12 +60,16 @@ Have your PythonAnywhere API token and username ready. You can find (or
60
60
  generate) your API token in the [API section of your PythonAnywhere
61
61
  account](https://www.pythonanywhere.com/account/#api_token).
62
62
 
63
- ### Desktop Extension - works with Claude Desktop
63
+ If your account is on `eu.pythonanywhere.com`, you also need to set
64
+ `PYTHONANYWHERE_SITE` to `eu.pythonanywhere.com` (it defaults to
65
+ `www.pythonanywhere.com`).
66
+
67
+ ### MCP Bundle - works with Claude Desktop
64
68
  Probably the most straightforward way to install the MCP server is to use
65
- the [desktop extension](https://github.com/anthropics/dxt/) for Claude Desktop.
69
+ the [MCP Bundle](https://github.com/modelcontextprotocol/mcpb) for Claude Desktop.
66
70
 
67
71
  1. Open Claude Desktop.
68
- 2. **[Download the latest .dxt file](https://github.com/pythonanywhere/pythonanywhere-mcp-server/releases/latest/download/pythonanywhere-mcp-server.dxt)**.
72
+ 2. **[Download the latest .mcpb file](https://github.com/pythonanywhere/pythonanywhere-mcp-server/releases/latest/download/pythonanywhere-mcp-server.mcpb)**.
69
73
  3. Double-click on the downloaded .dxt file or drag the file into the window.
70
74
  4. Configure your PythonAnywhere API token and username.
71
75
  5. Restart Claude Desktop.
@@ -75,7 +79,7 @@ Run:
75
79
  ```bash
76
80
  claude mcp add pythonanywhere-mcp-server \
77
81
  -e API_TOKEN=yourpythonanywhereapitoken \
78
- -e LOGNAME=yourpythonanywhereusername \
82
+ -e PYTHONANYWHERE_USERNAME=yourpythonanywhereusername \
79
83
  -- uvx pythonanywhere-mcp-server
80
84
  ```
81
85
 
@@ -91,7 +95,7 @@ Add it to your `mcp.json`.
91
95
  "args": ["pythonanywhere-mcp-server"],
92
96
  "env": {
93
97
  "API_TOKEN": "yourpythonanywhereapitoken",
94
- "LOGNAME": "yourpythonanywhereusername"
98
+ "PYTHONANYWHERE_USERNAME": "yourpythonanywhereusername"
95
99
  }
96
100
  }
97
101
  }
@@ -111,7 +115,7 @@ for Cursor).
111
115
  "args": ["pythonanywhere-mcp-server"],
112
116
  "env": {
113
117
  "API_TOKEN": "yourpythonanywhereapitoken",
114
- "LOGNAME": "yourpythonanywhereusername"
118
+ "PYTHONANYWHERE_USERNAME": "yourpythonanywhereusername"
115
119
  }
116
120
  }
117
121
  }
@@ -34,12 +34,16 @@ Have your PythonAnywhere API token and username ready. You can find (or
34
34
  generate) your API token in the [API section of your PythonAnywhere
35
35
  account](https://www.pythonanywhere.com/account/#api_token).
36
36
 
37
- ### Desktop Extension - works with Claude Desktop
37
+ If your account is on `eu.pythonanywhere.com`, you also need to set
38
+ `PYTHONANYWHERE_SITE` to `eu.pythonanywhere.com` (it defaults to
39
+ `www.pythonanywhere.com`).
40
+
41
+ ### MCP Bundle - works with Claude Desktop
38
42
  Probably the most straightforward way to install the MCP server is to use
39
- the [desktop extension](https://github.com/anthropics/dxt/) for Claude Desktop.
43
+ the [MCP Bundle](https://github.com/modelcontextprotocol/mcpb) for Claude Desktop.
40
44
 
41
45
  1. Open Claude Desktop.
42
- 2. **[Download the latest .dxt file](https://github.com/pythonanywhere/pythonanywhere-mcp-server/releases/latest/download/pythonanywhere-mcp-server.dxt)**.
46
+ 2. **[Download the latest .mcpb file](https://github.com/pythonanywhere/pythonanywhere-mcp-server/releases/latest/download/pythonanywhere-mcp-server.mcpb)**.
43
47
  3. Double-click on the downloaded .dxt file or drag the file into the window.
44
48
  4. Configure your PythonAnywhere API token and username.
45
49
  5. Restart Claude Desktop.
@@ -49,7 +53,7 @@ Run:
49
53
  ```bash
50
54
  claude mcp add pythonanywhere-mcp-server \
51
55
  -e API_TOKEN=yourpythonanywhereapitoken \
52
- -e LOGNAME=yourpythonanywhereusername \
56
+ -e PYTHONANYWHERE_USERNAME=yourpythonanywhereusername \
53
57
  -- uvx pythonanywhere-mcp-server
54
58
  ```
55
59
 
@@ -65,7 +69,7 @@ Add it to your `mcp.json`.
65
69
  "args": ["pythonanywhere-mcp-server"],
66
70
  "env": {
67
71
  "API_TOKEN": "yourpythonanywhereapitoken",
68
- "LOGNAME": "yourpythonanywhereusername"
72
+ "PYTHONANYWHERE_USERNAME": "yourpythonanywhereusername"
69
73
  }
70
74
  }
71
75
  }
@@ -85,7 +89,7 @@ for Cursor).
85
89
  "args": ["pythonanywhere-mcp-server"],
86
90
  "env": {
87
91
  "API_TOKEN": "yourpythonanywhereapitoken",
88
- "LOGNAME": "yourpythonanywhereusername"
92
+ "PYTHONANYWHERE_USERNAME": "yourpythonanywhereusername"
89
93
  }
90
94
  }
91
95
  }
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pythonanywhere-mcp-server"
7
- version = "0.0.8"
7
+ version = "0.0.9"
8
8
  description = "PythonAnywhere Model Context Protocol Server"
9
9
  authors = [
10
10
  {name = "PythonAnywhere Developers", email = "developers@pythonanywhere.com"}
@@ -12,7 +12,7 @@ authors = [
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.13"
14
14
  dependencies = [
15
- "pythonanywhere-core>=0.2.9",
15
+ "pythonanywhere-core>=0.3.0",
16
16
  "mcp[cli]",
17
17
  ]
18
18
  classifiers = [
@@ -0,0 +1 @@
1
+ __version__ = "0.0.9"
@@ -44,6 +44,27 @@ def register_file_tools(mcp: FastMCP) -> None:
44
44
  except Exception as exc:
45
45
  raise RuntimeError(f"Failed to upload text file: {str(exc)}") from exc
46
46
 
47
+ @mcp.tool()
48
+ def upload_directory(local_dir_path: str, remote_dir_path: str) -> str:
49
+ """
50
+ Upload a local directory to PythonAnywhere, preserving directory structure.
51
+
52
+ Recursively walks the local directory and uploads each file.
53
+ Empty directories are preserved.
54
+
55
+ Args:
56
+ local_dir_path (str): The absolute path to the local directory to upload.
57
+ remote_dir_path (str): The absolute path on PythonAnywhere where the directory will be uploaded.
58
+
59
+ Returns:
60
+ str: Status message indicating upload result.
61
+ """
62
+ try:
63
+ Files().tree_post(local_dir_path, remote_dir_path)
64
+ return f"Uploaded {local_dir_path} to {remote_dir_path}."
65
+ except Exception as exc:
66
+ raise RuntimeError(f"Failed to upload directory: {str(exc)}") from exc
67
+
47
68
  @mcp.tool()
48
69
  def delete_path(path: str) -> str:
49
70
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonanywhere-mcp-server
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: PythonAnywhere Model Context Protocol Server
5
5
  Author-email: PythonAnywhere Developers <developers@pythonanywhere.com>
6
6
  License-Expression: MIT
@@ -17,7 +17,7 @@ Classifier: Topic :: Utilities
17
17
  Requires-Python: >=3.13
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: pythonanywhere-core>=0.2.9
20
+ Requires-Dist: pythonanywhere-core>=0.3.0
21
21
  Requires-Dist: mcp[cli]
22
22
  Provides-Extra: test
23
23
  Requires-Dist: pytest; extra == "test"
@@ -60,12 +60,16 @@ Have your PythonAnywhere API token and username ready. You can find (or
60
60
  generate) your API token in the [API section of your PythonAnywhere
61
61
  account](https://www.pythonanywhere.com/account/#api_token).
62
62
 
63
- ### Desktop Extension - works with Claude Desktop
63
+ If your account is on `eu.pythonanywhere.com`, you also need to set
64
+ `PYTHONANYWHERE_SITE` to `eu.pythonanywhere.com` (it defaults to
65
+ `www.pythonanywhere.com`).
66
+
67
+ ### MCP Bundle - works with Claude Desktop
64
68
  Probably the most straightforward way to install the MCP server is to use
65
- the [desktop extension](https://github.com/anthropics/dxt/) for Claude Desktop.
69
+ the [MCP Bundle](https://github.com/modelcontextprotocol/mcpb) for Claude Desktop.
66
70
 
67
71
  1. Open Claude Desktop.
68
- 2. **[Download the latest .dxt file](https://github.com/pythonanywhere/pythonanywhere-mcp-server/releases/latest/download/pythonanywhere-mcp-server.dxt)**.
72
+ 2. **[Download the latest .mcpb file](https://github.com/pythonanywhere/pythonanywhere-mcp-server/releases/latest/download/pythonanywhere-mcp-server.mcpb)**.
69
73
  3. Double-click on the downloaded .dxt file or drag the file into the window.
70
74
  4. Configure your PythonAnywhere API token and username.
71
75
  5. Restart Claude Desktop.
@@ -75,7 +79,7 @@ Run:
75
79
  ```bash
76
80
  claude mcp add pythonanywhere-mcp-server \
77
81
  -e API_TOKEN=yourpythonanywhereapitoken \
78
- -e LOGNAME=yourpythonanywhereusername \
82
+ -e PYTHONANYWHERE_USERNAME=yourpythonanywhereusername \
79
83
  -- uvx pythonanywhere-mcp-server
80
84
  ```
81
85
 
@@ -91,7 +95,7 @@ Add it to your `mcp.json`.
91
95
  "args": ["pythonanywhere-mcp-server"],
92
96
  "env": {
93
97
  "API_TOKEN": "yourpythonanywhereapitoken",
94
- "LOGNAME": "yourpythonanywhereusername"
98
+ "PYTHONANYWHERE_USERNAME": "yourpythonanywhereusername"
95
99
  }
96
100
  }
97
101
  }
@@ -111,7 +115,7 @@ for Cursor).
111
115
  "args": ["pythonanywhere-mcp-server"],
112
116
  "env": {
113
117
  "API_TOKEN": "yourpythonanywhereapitoken",
114
- "LOGNAME": "yourpythonanywhereusername"
118
+ "PYTHONANYWHERE_USERNAME": "yourpythonanywhereusername"
115
119
  }
116
120
  }
117
121
  }
@@ -1,4 +1,4 @@
1
- pythonanywhere-core>=0.2.9
1
+ pythonanywhere-core>=0.3.0
2
2
  mcp[cli]
3
3
 
4
4
  [test]
@@ -62,6 +62,23 @@ def test_delete_path_exception(mcp, mocker):
62
62
  assert "Failed to delete path: delete error" in str(exc)
63
63
 
64
64
 
65
+ def test_upload_directory(mcp, mocker):
66
+ file_tools.register_file_tools(mcp)
67
+ mock_files = mocker.patch("tools.file.Files", autospec=True)
68
+ result = mcp.call_tool("upload_directory", {"local_dir_path": "/local/myapp", "remote_dir_path": "/home/user/myapp"})
69
+ mock_files.return_value.tree_post.assert_called_with("/local/myapp", "/home/user/myapp")
70
+ assert result == "Uploaded /local/myapp to /home/user/myapp."
71
+
72
+
73
+ def test_upload_directory_exception(mcp, mocker):
74
+ file_tools.register_file_tools(mcp)
75
+ mock_files = mocker.patch("tools.file.Files", autospec=True)
76
+ mock_files.return_value.tree_post.side_effect = Exception("upload dir error")
77
+ with pytest.raises(RuntimeError) as exc:
78
+ mcp.call_tool("upload_directory", {"local_dir_path": "/local/myapp", "remote_dir_path": "/home/user/myapp"})
79
+ assert "Failed to upload directory: upload dir error" in str(exc)
80
+
81
+
65
82
  def test_directory_tree(mcp, mocker):
66
83
  file_tools.register_file_tools(mcp)
67
84
  mock_files = mocker.patch("tools.file.Files", autospec=True)
@@ -1 +0,0 @@
1
- __version__ = "0.0.8"