Use configured contacts address book
All checks were successful
Build And Test / publish (push) Successful in 47s
All checks were successful
Build And Test / publish (push) Successful in 47s
This commit is contained in:
@@ -54,7 +54,7 @@ CALDAV_PASSWORD=your-caldav-password
|
||||
CARDDAV_URL=https://carddav.example.com/dav
|
||||
CARDDAV_USERNAME=user@example.com
|
||||
CARDDAV_PASSWORD=your-carddav-password
|
||||
CONTACTS_ADDRESSBOOK_ID=/dav/addressbooks/users/user@example.com/contacts/
|
||||
CONTACTS_ADDRESSBOOK_URL=https://carddav.example.com/dav/addressbooks/users/user@example.com/contacts/
|
||||
|
||||
# =============================================================================
|
||||
# Cache Configuration
|
||||
|
||||
@@ -94,10 +94,10 @@ ICS_CALENDAR_TIMEOUT=20
|
||||
CARDDAV_URL=https://carddav.example.com/dav
|
||||
CARDDAV_USERNAME=you@example.com
|
||||
CARDDAV_PASSWORD=your-password
|
||||
CONTACTS_ADDRESSBOOK_ID=/dav/addressbooks/users/you@example.com/contacts/
|
||||
CONTACTS_ADDRESSBOOK_URL=https://carddav.example.com/dav/addressbooks/users/you@example.com/contacts/
|
||||
```
|
||||
|
||||
Contacts tools always use `CONTACTS_ADDRESSBOOK_ID`. Listing address books is not exposed via MCP.
|
||||
Contacts tools always use `CONTACTS_ADDRESSBOOK_URL` (full CardDAV address book URL). Listing address books is not exposed via MCP.
|
||||
|
||||
ICS calendars are optional and read-only. Set `ICS_CALENDARS` to a comma-separated list of entries, each as `name|url` or just `url` if you want the name inferred.
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@ class Settings(BaseSettings):
|
||||
carddav_url: Optional[str] = Field(default=None, alias="CARDDAV_URL")
|
||||
carddav_username: Optional[str] = Field(default=None, alias="CARDDAV_USERNAME")
|
||||
carddav_password: Optional[SecretStr] = Field(default=None, alias="CARDDAV_PASSWORD")
|
||||
contacts_addressbook_id: Optional[str] = Field(
|
||||
contacts_addressbook_url: Optional[str] = Field(
|
||||
default=None,
|
||||
alias="CONTACTS_ADDRESSBOOK_ID",
|
||||
alias="CONTACTS_ADDRESSBOOK_URL",
|
||||
)
|
||||
|
||||
# SQLite Cache
|
||||
@@ -154,7 +154,7 @@ class Settings(BaseSettings):
|
||||
self.carddav_url,
|
||||
self.carddav_username,
|
||||
self.carddav_password,
|
||||
self.contacts_addressbook_id,
|
||||
self.contacts_addressbook_url,
|
||||
])
|
||||
|
||||
def is_notification_configured(self) -> bool:
|
||||
|
||||
@@ -351,7 +351,6 @@ class ContactsService:
|
||||
def delete_contact(self, contact_id: str, addressbook_id: Optional[str] = None) -> OperationResult:
|
||||
try:
|
||||
client = self._get_client()
|
||||
addressbook_id = self._resolve_addressbook_id(addressbook_id)
|
||||
|
||||
# Build URL
|
||||
contact_url = self._build_url(contact_id)
|
||||
@@ -375,7 +374,7 @@ class ContactsService:
|
||||
return OperationResult(success=False, message=str(e))
|
||||
|
||||
def _parse_vcard(
|
||||
self, vcard_data: str, addressbook_id: str, href: str
|
||||
self, vcard_data: str, addressbook_id: Optional[str], href: str
|
||||
) -> Optional[Contact]:
|
||||
try:
|
||||
vcard = vobject.readOne(vcard_data)
|
||||
@@ -471,9 +470,10 @@ class ContactsService:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
resolved_addressbook_id = addressbook_id or self._derive_addressbook_id(href)
|
||||
return Contact(
|
||||
id=href,
|
||||
addressbook_id=addressbook_id,
|
||||
addressbook_id=resolved_addressbook_id,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
display_name=display_name,
|
||||
@@ -486,9 +486,15 @@ class ContactsService:
|
||||
birthday=birthday,
|
||||
)
|
||||
|
||||
def _derive_addressbook_id(self, contact_href: str) -> str:
|
||||
if "/" not in contact_href:
|
||||
return contact_href
|
||||
base = contact_href.rsplit("/", 1)[0]
|
||||
return f"{base}/"
|
||||
|
||||
def _resolve_addressbook_id(self, addressbook_id: Optional[str]) -> str:
|
||||
if addressbook_id:
|
||||
return addressbook_id
|
||||
if self.settings.contacts_addressbook_id:
|
||||
return self.settings.contacts_addressbook_id
|
||||
raise ValueError("CONTACTS_ADDRESSBOOK_ID must be set to use contacts tools")
|
||||
if self.settings.contacts_addressbook_url:
|
||||
return self.settings.contacts_addressbook_url
|
||||
raise ValueError("CONTACTS_ADDRESSBOOK_URL must be set to use contacts tools")
|
||||
|
||||
@@ -70,7 +70,6 @@ def register_contacts_tools(mcp: FastMCP, service: ContactsService):
|
||||
birthday: Birthday in ISO format (YYYY-MM-DD)
|
||||
"""
|
||||
result = service.create_contact(
|
||||
addressbook_id=None,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
display_name=display_name,
|
||||
@@ -115,7 +114,6 @@ def register_contacts_tools(mcp: FastMCP, service: ContactsService):
|
||||
"""
|
||||
result = service.update_contact(
|
||||
contact_id,
|
||||
addressbook_id=None,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
display_name=display_name,
|
||||
|
||||
@@ -181,15 +181,16 @@ def register_email_tools(mcp: FastMCP, service: EmailService):
|
||||
reply_all: Whether to include original recipients when replying (default: False)
|
||||
"""
|
||||
result = service.save_draft(
|
||||
to,
|
||||
subject,
|
||||
body,
|
||||
cc,
|
||||
bcc,
|
||||
mailbox,
|
||||
in_reply_to_email_id,
|
||||
in_reply_to_mailbox,
|
||||
reply_all,
|
||||
to=to,
|
||||
subject=subject,
|
||||
body=body,
|
||||
cc=cc,
|
||||
bcc=bcc,
|
||||
html_body=None,
|
||||
mailbox=mailbox,
|
||||
in_reply_to_email_id=in_reply_to_email_id,
|
||||
in_reply_to_mailbox=in_reply_to_mailbox,
|
||||
reply_all=reply_all,
|
||||
)
|
||||
return result.model_dump()
|
||||
|
||||
@@ -223,16 +224,17 @@ def register_email_tools(mcp: FastMCP, service: EmailService):
|
||||
reply_all: Whether to include original recipients when replying (default: False)
|
||||
"""
|
||||
result = service.update_draft(
|
||||
email_id,
|
||||
mailbox,
|
||||
to,
|
||||
subject,
|
||||
body,
|
||||
cc,
|
||||
bcc,
|
||||
in_reply_to_email_id,
|
||||
in_reply_to_mailbox,
|
||||
reply_all,
|
||||
email_id=email_id,
|
||||
mailbox=mailbox,
|
||||
to=to,
|
||||
subject=subject,
|
||||
body=body,
|
||||
cc=cc,
|
||||
bcc=bcc,
|
||||
html_body=None,
|
||||
in_reply_to_email_id=in_reply_to_email_id,
|
||||
in_reply_to_mailbox=in_reply_to_mailbox,
|
||||
reply_all=reply_all,
|
||||
)
|
||||
return result.model_dump()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user