Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b348ce9ea1 | |||
| ee9474bf06 | |||
| 4bb1e4cf50 | |||
| 02e55a4636 | |||
| e1ecf0cdbf | |||
| a9db4fb0af | |||
| 26a6f154a9 | |||
| 8d8e6d9c99 | |||
| d41076b1a0 | |||
| 65a704869d | |||
| cfd4df971d | |||
| 83d4c33b31 | |||
| 76381c3365 | |||
| a91d6ae9f7 | |||
| 56d8d7b8f0 | |||
| c3e2c28f6b | |||
| 3a39e525e1 | |||
| c289646d27 |
@@ -47,7 +47,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
|
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6
|
||||||
with:
|
with:
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM ghcr.io/astral-sh/uv:python3.11-alpine@sha256:c77e10ca22ef1021e1cafcbaee9595b5f9d8d9f2b1fe4cc7e908b981bab73ee7
|
FROM ghcr.io/astral-sh/uv:python3.11-alpine@sha256:2d9058ac1ecdd9b1baacae5362c8f40aa20137c6a1596e24eb956ff7469a9537
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
note_id = 487 # ID of the note we just created
|
|
||||||
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
# Check if image exists
|
|
||||||
image_path = 'sample_image.png'
|
|
||||||
if not os.path.exists(image_path):
|
|
||||||
print(f"Error: Image file '{image_path}' not found")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Read the image
|
|
||||||
with open(image_path, 'rb') as f:
|
|
||||||
image_content = f.read()
|
|
||||||
|
|
||||||
print(f"Attaching image to note {note_id}...")
|
|
||||||
try:
|
|
||||||
# Attach the image to the note
|
|
||||||
upload_response = client.add_note_attachment(
|
|
||||||
note_id=note_id,
|
|
||||||
filename="sample_image.png",
|
|
||||||
content=image_content,
|
|
||||||
mime_type="image/png"
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Image attached successfully (Status: {upload_response['status_code']}).")
|
|
||||||
|
|
||||||
# Now get the current note to get its etag
|
|
||||||
note = client.notes_get_note(note_id=note_id)
|
|
||||||
etag = note["etag"]
|
|
||||||
|
|
||||||
# Update the note content to include the image references
|
|
||||||
updated_content = f"""# Note with Visible Image Demo
|
|
||||||
|
|
||||||
This note demonstrates how to properly embed an image in Nextcloud Notes so it's visible in the browser interface.
|
|
||||||
|
|
||||||
We'll include the sample red square image we created earlier using both Markdown and HTML methods.
|
|
||||||
|
|
||||||
## Method 1: Markdown Image Syntax
|
|
||||||

|
|
||||||
|
|
||||||
## Method 2: HTML Image Tag
|
|
||||||
<img src=".attachments.{note_id}/sample_image.png" alt="Sample Red Square Image" width="300" />
|
|
||||||
|
|
||||||
## Image Path Details
|
|
||||||
The image is stored at: `/Notes/.attachments.{note_id}/sample_image.png`
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Update the note with the references to the image
|
|
||||||
updated_note = client.notes_update_note(
|
|
||||||
note_id=note_id,
|
|
||||||
etag=etag,
|
|
||||||
content=updated_content
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Note updated with image references. You can now view it in the browser.")
|
|
||||||
print(f"Note URL: /index.php/apps/notes/#/note/{note_id}")
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
note_id = 420 # ID of the note we created earlier
|
|
||||||
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
# Check if image exists
|
|
||||||
image_path = 'sample_image.png'
|
|
||||||
if not os.path.exists(image_path):
|
|
||||||
print(f"Error: Image file '{image_path}' not found")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Read the image
|
|
||||||
with open(image_path, 'rb') as f:
|
|
||||||
image_content = f.read()
|
|
||||||
|
|
||||||
print(f"Attaching image to note {note_id}...")
|
|
||||||
try:
|
|
||||||
# Attach the image to the note
|
|
||||||
upload_response = client.add_note_attachment(
|
|
||||||
note_id=note_id,
|
|
||||||
filename="sample_image.png",
|
|
||||||
content=image_content,
|
|
||||||
mime_type="image/png"
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Image attached successfully (Status: {upload_response['status_code']}).")
|
|
||||||
print(f"Note URL: /index.php/apps/notes/#/note/{note_id}")
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error attaching image: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
note_id = 420 # ID of the note with the image attachment
|
|
||||||
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
# Get the note again to see the updated content
|
|
||||||
try:
|
|
||||||
note = client.notes_get_note(note_id=note_id)
|
|
||||||
print(f"Retrieved note: {note['title']}")
|
|
||||||
print("\nCURRENT NOTE CONTENT:")
|
|
||||||
print("-" * 50)
|
|
||||||
print(note['content'])
|
|
||||||
print("-" * 50)
|
|
||||||
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error retrieving note: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
+3
-3
@@ -3,7 +3,7 @@ services:
|
|||||||
# https://hub.docker.com/_/mariadb
|
# https://hub.docker.com/_/mariadb
|
||||||
db:
|
db:
|
||||||
# Note: Check the recommend version here: https://docs.nextcloud.com/server/latest/admin_manual/installation/system_requirements.html#server
|
# Note: Check the recommend version here: https://docs.nextcloud.com/server/latest/admin_manual/installation/system_requirements.html#server
|
||||||
image: mariadb:lts@sha256:663d4d3e652220e3c618564dd401ae33ee5ea2b31aafd13c6d4e8ed29b8df733
|
image: mariadb:lts@sha256:49117dcc565cf51aa57ac5fca59ab31213402ff0eae6ffc13c46a37b938f7e4b
|
||||||
restart: always
|
restart: always
|
||||||
command: --transaction-isolation=READ-COMMITTED
|
command: --transaction-isolation=READ-COMMITTED
|
||||||
volumes:
|
volumes:
|
||||||
@@ -17,11 +17,11 @@ services:
|
|||||||
# Note: Redis is an external service. You can find more information about the configuration here:
|
# Note: Redis is an external service. You can find more information about the configuration here:
|
||||||
# https://hub.docker.com/_/redis
|
# https://hub.docker.com/_/redis
|
||||||
redis:
|
redis:
|
||||||
image: redis:alpine@sha256:f773b35a95e170d92dd4214a3ec4859b1b7960bf56896ae687646d695f311187
|
image: redis:alpine@sha256:62b5498c91778f738f0efbf0a6fd5b434011235a3e7b5f2ed4a2c0c63bb1c786
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
app:
|
app:
|
||||||
image: nextcloud@sha256:ad4da6574b6dcb75c185128b091e6ac613f0aabda7ce7f75c9730d9f706e37d0
|
image: nextcloud:31.0.5
|
||||||
#user: www-data:www-data
|
#user: www-data:www-data
|
||||||
restart: always
|
restart: always
|
||||||
#post_start:
|
#post_start:
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ authors = [
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mcp[cli] (>=1.7,<1.8)",
|
"mcp[cli] (>=1.9,<1.10)",
|
||||||
"httpx (>=0.28.1,<0.29.0)",
|
"httpx (>=0.28.1,<0.29.0)",
|
||||||
"pillow (>=11.2.1,<12.0.0)"
|
"pillow (>=11.2.1,<12.0.0)"
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
from PIL import Image, ImageDraw
|
|
||||||
|
|
||||||
# Create a simple image (a red square with some text)
|
|
||||||
img = Image.new('RGB', (200, 200), color = (255, 255, 255))
|
|
||||||
draw = ImageDraw.Draw(img)
|
|
||||||
draw.rectangle([(20, 20), (180, 180)], fill=(255, 0, 0))
|
|
||||||
draw.text((40, 100), "Nextcloud MCP", fill=(255, 255, 255))
|
|
||||||
img.save('sample_image.png')
|
|
||||||
|
|
||||||
print("Image created successfully: sample_image.png")
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
# 1. Create a new test note
|
|
||||||
test_title = "Test Note for Deletion with Attachment"
|
|
||||||
print(f"Creating test note: {test_title}...")
|
|
||||||
note = client.notes_create_note(
|
|
||||||
title=test_title,
|
|
||||||
content="This note will be deleted but its attachment should remain.",
|
|
||||||
category="Test"
|
|
||||||
)
|
|
||||||
note_id = note["id"]
|
|
||||||
print(f"Note created with ID: {note_id}")
|
|
||||||
|
|
||||||
# 2. Attach the existing image to the note
|
|
||||||
print(f"Attaching image to note {note_id}...")
|
|
||||||
with open("sample_image.png", 'rb') as f:
|
|
||||||
image_content = f.read()
|
|
||||||
|
|
||||||
upload_response = client.add_note_attachment(
|
|
||||||
note_id=note_id,
|
|
||||||
filename="deletion_test_image.png",
|
|
||||||
content=image_content,
|
|
||||||
mime_type="image/png"
|
|
||||||
)
|
|
||||||
print(f"Image attached successfully (Status: {upload_response['status_code']}).")
|
|
||||||
|
|
||||||
# 3. Verify the attachment exists
|
|
||||||
print(f"Verifying attachment exists...")
|
|
||||||
content, mime_type = client.get_note_attachment(
|
|
||||||
note_id=note_id,
|
|
||||||
filename="deletion_test_image.png"
|
|
||||||
)
|
|
||||||
print(f"Attachment verified (Size: {len(content)} bytes)")
|
|
||||||
|
|
||||||
# 4. Delete the note
|
|
||||||
print(f"\nDeleting note {note_id}...")
|
|
||||||
response = client.notes_delete_note(note_id=note_id)
|
|
||||||
print(f"Note deleted successfully.")
|
|
||||||
|
|
||||||
# Wait a moment for deletion to process
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# 5. Verify the note is gone
|
|
||||||
print("\nVerifying note is deleted...")
|
|
||||||
try:
|
|
||||||
client.notes_get_note(note_id=note_id)
|
|
||||||
print("ERROR: Note still exists!")
|
|
||||||
return 1
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Note confirmed deleted (404 Not Found expected): {e}")
|
|
||||||
|
|
||||||
# 6. Check if attachment still exists (expected behavior)
|
|
||||||
print("\nChecking if attachment still exists (orphaned)...")
|
|
||||||
try:
|
|
||||||
content, mime_type = client.get_note_attachment(
|
|
||||||
note_id=note_id,
|
|
||||||
filename="deletion_test_image.png"
|
|
||||||
)
|
|
||||||
print("EXPECTED BEHAVIOR: Attachment still exists after note deletion!")
|
|
||||||
print(f"Attachment size: {len(content)} bytes")
|
|
||||||
print(f"This matches the documented behavior of Nextcloud Notes.")
|
|
||||||
|
|
||||||
# Save the orphaned attachment to verify
|
|
||||||
output_path = "orphaned_attachment.png"
|
|
||||||
with open(output_path, 'wb') as f:
|
|
||||||
f.write(content)
|
|
||||||
print(f"Saved orphaned attachment to: {output_path}")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Unexpected: Attachment was deleted with note: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
note_id = 420 # ID of the note with the image attachment
|
|
||||||
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
# First get the current note
|
|
||||||
try:
|
|
||||||
note = client.notes_get_note(note_id=note_id)
|
|
||||||
print(f"Retrieved note: {note['title']}")
|
|
||||||
|
|
||||||
# Update the note content to include a direct reference to the image
|
|
||||||
updated_content = f"""# Note with Image Attachment
|
|
||||||
|
|
||||||
This note demonstrates attaching images to Nextcloud Notes.
|
|
||||||
|
|
||||||
An image will be attached to this note as a demonstration.
|
|
||||||
|
|
||||||
## Image Reference
|
|
||||||
|
|
||||||
The image is attached but not displayed inline in the Notes UI.
|
|
||||||
Attachments in Nextcloud Notes exist as separate files in the .attachments.{note_id}
|
|
||||||
directory but aren't automatically embedded in the note content.
|
|
||||||
|
|
||||||
You can view the image by going to the Files app and navigating to:
|
|
||||||
/Notes/.attachments.{note_id}/sample_image.png
|
|
||||||
|
|
||||||
## Orphaned Attachments
|
|
||||||
|
|
||||||
When notes are deleted, their attachments remain in the system.
|
|
||||||
This is the expected behavior of the official Nextcloud Notes app.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Update the note with the new content
|
|
||||||
updated_note = client.notes_update_note(
|
|
||||||
note_id=note_id,
|
|
||||||
etag=note['etag'],
|
|
||||||
content=updated_content
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Note updated successfully with image reference information.")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error updating note: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
note_id = 487 # ID of the note with the issue
|
|
||||||
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Get the current note to get its etag
|
|
||||||
note = client.notes_get_note(note_id=note_id)
|
|
||||||
etag = note["etag"]
|
|
||||||
|
|
||||||
# Update the note content with correct image reference syntax
|
|
||||||
updated_content = f"""# Note with Visible Image Demo
|
|
||||||
|
|
||||||
This note demonstrates how to properly embed an image in Nextcloud Notes so it's visible in the browser interface.
|
|
||||||
|
|
||||||
We'll include the sample red square image we created earlier using both Markdown and HTML methods.
|
|
||||||
|
|
||||||
## Method 1: Markdown Image Syntax
|
|
||||||

|
|
||||||
|
|
||||||
## Method 2: HTML Image Tag
|
|
||||||
<img src=".attachments.{note_id}/sample_image.png" alt="Sample Red Square Image" width="300" />
|
|
||||||
|
|
||||||
## Image Path Details
|
|
||||||
The image is stored at: `/Notes/.attachments.{note_id}/sample_image.png`
|
|
||||||
|
|
||||||
## Note on Image Embedding
|
|
||||||
In Nextcloud Notes, images must be referenced with a period at the beginning of the path. The correct format is:
|
|
||||||
`.attachments.{note_id}/filename.png`
|
|
||||||
|
|
||||||
Without the leading period, the image won't display correctly.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Update the note with the corrected image references
|
|
||||||
updated_note = client.notes_update_note(
|
|
||||||
note_id=note_id,
|
|
||||||
etag=etag,
|
|
||||||
content=updated_content
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Note updated with corrected image references.")
|
|
||||||
print(f"Note URL: /index.php/apps/notes/#/note/{note_id}")
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import base64
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient, HTTPStatusError
|
|
||||||
import logging
|
|
||||||
import time
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
def test_webdav_auth_with_attachment():
|
|
||||||
"""
|
|
||||||
Test function to verify WebDAV authentication by attempting to use add_note_attachment.
|
|
||||||
"""
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
print("Client authentication type:", type(client._client.auth).__name__)
|
|
||||||
|
|
||||||
username = os.environ["NEXTCLOUD_USERNAME"]
|
|
||||||
webdav_base = client._get_webdav_base_path()
|
|
||||||
notes_path = f"{webdav_base}/Notes"
|
|
||||||
print(f"Target WebDAV Notes path for PROPFIND check: {notes_path}")
|
|
||||||
|
|
||||||
temp_note_id = None
|
|
||||||
try:
|
|
||||||
# 1. Create a temporary note to get a note_id
|
|
||||||
print("\nCreating a temporary note...")
|
|
||||||
temp_note_title = f"Temp Note for WebDAV Test - {int(time.time())}"
|
|
||||||
created_note = client.notes_create_note(title=temp_note_title, content="Test content")
|
|
||||||
temp_note_id = created_note.get("id")
|
|
||||||
if not temp_note_id:
|
|
||||||
print("Error: Failed to create temporary note.")
|
|
||||||
return 1
|
|
||||||
print(f"Temporary note created with ID: {temp_note_id}")
|
|
||||||
|
|
||||||
# 2. Attempt to add an attachment (this will trigger the internal PROPFIND)
|
|
||||||
print(f"\nTest: Attempting add_note_attachment for note_id {temp_note_id} (uses client's BasicAuth)")
|
|
||||||
dummy_content = b"This is a test attachment."
|
|
||||||
dummy_filename = "test_attachment.txt"
|
|
||||||
|
|
||||||
# The add_note_attachment method itself contains the PROPFIND check
|
|
||||||
# and will log details if it fails.
|
|
||||||
response_data = client.add_note_attachment(
|
|
||||||
note_id=temp_note_id,
|
|
||||||
filename=dummy_filename,
|
|
||||||
content=dummy_content,
|
|
||||||
mime_type="text/plain"
|
|
||||||
)
|
|
||||||
print(f"add_note_attachment response: {response_data}")
|
|
||||||
if response_data and response_data.get("status_code") in [201, 204]:
|
|
||||||
print("Success! add_note_attachment (and its internal PROPFIND) worked.")
|
|
||||||
else:
|
|
||||||
print("Failure or unexpected response from add_note_attachment.")
|
|
||||||
# The client.py logs should show details of the PROPFIND if it failed.
|
|
||||||
|
|
||||||
except HTTPStatusError as e:
|
|
||||||
print(f"HTTPStatusError during add_note_attachment: {e.response.status_code} - {e.response.text}")
|
|
||||||
if e.response.status_code == 401:
|
|
||||||
print("Reproduced 401 Unauthorized during add_note_attachment's PROPFIND check!")
|
|
||||||
else:
|
|
||||||
print("An HTTP error other than 401 occurred.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An unexpected error occurred: {str(e)}")
|
|
||||||
finally:
|
|
||||||
# 3. Clean up: Delete the temporary note
|
|
||||||
if temp_note_id:
|
|
||||||
print(f"\nCleaning up: Deleting temporary note ID {temp_note_id}...")
|
|
||||||
try:
|
|
||||||
client.notes_delete_note(note_id=temp_note_id)
|
|
||||||
print(f"Successfully deleted temporary note ID {temp_note_id}.")
|
|
||||||
except Exception as e_del:
|
|
||||||
print(f"Error deleting temporary note ID {temp_note_id}: {str(e_del)}")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(test_webdav_auth_with_attachment())
|
|
||||||
@@ -301,7 +301,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mcp"
|
name = "mcp"
|
||||||
version = "1.7.1"
|
version = "1.9.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "anyio" },
|
{ name = "anyio" },
|
||||||
@@ -314,9 +314,9 @@ dependencies = [
|
|||||||
{ name = "starlette" },
|
{ name = "starlette" },
|
||||||
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/25/ae/588691c45b38f4fbac07fa3d6d50cea44cc6b35d16ddfdf26e17a0467ab2/mcp-1.7.1.tar.gz", hash = "sha256:eb4f1f53bd717f75dda8a1416e00804b831a8f3c331e23447a03b78f04b43a6e", size = 230903, upload-time = "2025-05-02T17:01:56.403Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/bc/8d/0f4468582e9e97b0a24604b585c651dfd2144300ecffd1c06a680f5c8861/mcp-1.9.0.tar.gz", hash = "sha256:905d8d208baf7e3e71d70c82803b89112e321581bcd2530f9de0fe4103d28749", size = 281432, upload-time = "2025-05-15T18:51:06.615Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/ae/79/fe0e20c3358997a80911af51bad927b5ea2f343ef95ab092b19c9cc48b59/mcp-1.7.1-py3-none-any.whl", hash = "sha256:f7e6108977db6d03418495426c7ace085ba2341b75197f8727f96f9cfd30057a", size = 100365, upload-time = "2025-05-02T17:01:54.674Z" },
|
{ url = "https://files.pythonhosted.org/packages/a5/d5/22e36c95c83c80eb47c83f231095419cf57cf5cca5416f1c960032074c78/mcp-1.9.0-py3-none-any.whl", hash = "sha256:9dfb89c8c56f742da10a5910a1f64b0d2ac2c3ed2bd572ddb1cfab7f35957178", size = 125082, upload-time = "2025-05-15T18:51:04.916Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.optional-dependencies]
|
[package.optional-dependencies]
|
||||||
@@ -345,7 +345,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nextcloud-mcp-server"
|
name = "nextcloud-mcp-server"
|
||||||
version = "0.1.0"
|
version = "0.1.3"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "httpx" },
|
{ name = "httpx" },
|
||||||
@@ -364,7 +364,7 @@ dev = [
|
|||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "httpx", specifier = ">=0.28.1,<0.29.0" },
|
{ name = "httpx", specifier = ">=0.28.1,<0.29.0" },
|
||||||
{ name = "mcp", extras = ["cli"], specifier = ">=1.7,<1.8" },
|
{ name = "mcp", extras = ["cli"], specifier = ">=1.9,<1.10" },
|
||||||
{ name = "pillow", specifier = ">=11.2.1,<12.0.0" },
|
{ name = "pillow", specifier = ">=11.2.1,<12.0.0" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
from nextcloud_mcp_server.client import NextcloudClient
|
|
||||||
|
|
||||||
def main():
|
|
||||||
note_id = 420 # ID of the note we created earlier
|
|
||||||
|
|
||||||
# Create client
|
|
||||||
client = NextcloudClient.from_env()
|
|
||||||
|
|
||||||
# First verify the note exists
|
|
||||||
print(f"Retrieving note {note_id}...")
|
|
||||||
try:
|
|
||||||
note = client.notes_get_note(note_id=note_id)
|
|
||||||
print(f"Note retrieved: {note['title']}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error retrieving note: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Now try to get the image attachment
|
|
||||||
attachment_filename = "sample_image.png"
|
|
||||||
print(f"Retrieving attachment '{attachment_filename}' from note {note_id}...")
|
|
||||||
try:
|
|
||||||
content, mime_type = client.get_note_attachment(
|
|
||||||
note_id=note_id,
|
|
||||||
filename=attachment_filename
|
|
||||||
)
|
|
||||||
print(f"Attachment retrieved successfully!")
|
|
||||||
print(f"MIME type: {mime_type}")
|
|
||||||
print(f"Content size: {len(content)} bytes")
|
|
||||||
|
|
||||||
# Save the retrieved image to verify it's the same
|
|
||||||
output_path = "retrieved_image.png"
|
|
||||||
with open(output_path, 'wb') as f:
|
|
||||||
f.write(content)
|
|
||||||
print(f"Saved retrieved image to: {output_path}")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error retrieving attachment: {e}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
Reference in New Issue
Block a user