Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions src/dedalus_labs/lib/mcp/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

from ..crypto import encrypt_credentials, fetch_encryption_key, fetch_encryption_key_sync
from .protocols import CredentialProtocol
from .wire import serialize_mcp_servers
from .wire import serialize_mcp_servers, slug_to_connection_name

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -165,35 +165,46 @@ def _encrypt_credentials(
return EncryptedCredentials(**encrypted)


def _credentials_for_server(
name: str,
all_creds: Dict[str, str],
) -> Optional[Dict[str, str]]:
"""Return the subset of *all_creds* that belongs to *name*, or None."""
conn = slug_to_connection_name(name)
blob = all_creds.get(conn)
return {conn: blob} if blob else None
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated


def _embed_credentials(
servers: List[MCPServerItem],
encrypted: EncryptedCredentials,
) -> List[MCPServerSpec]:
"""Embed encrypted credentials into each server spec.

Converts slug strings to full specs and adds credentials to all servers.
Each server receives only its own credentials, matched by connection name
via :func:`~dedalus_labs.lib.mcp.wire.slug_to_connection_name`.

Args:
servers: Serialized MCP servers (slug strings or spec dicts).
encrypted: EncryptedCredentials instance.

Returns:
List of MCPServerSpec dicts with credentials embedded.
List of MCPServerSpec dicts with per-server credentials embedded.

"""
creds_dict = encrypted.to_dict()
all_creds = encrypted.to_dict()
result: List[MCPServerSpec] = []

for server in servers:
if isinstance(server, str):
creds = _credentials_for_server(server, all_creds)
if server.startswith(("http://", "https://")):
result.append({"url": server, "name": server, "credentials": creds_dict})
result.append({"url": server, "name": server, "credentials": creds})
else:
result.append({"slug": server, "name": server, "credentials": creds_dict})
result.append({"slug": server, "name": server, "credentials": creds})
elif isinstance(server, dict):
# Existing spec -> add name (if missing) and credentials
name = server.get("name") or server.get("slug") or server.get("url") or ""
spec: MCPServerSpec = {**server, "name": name, "credentials": creds_dict}
result.append(spec)
creds = _credentials_for_server(name, all_creds)
result.append({**server, "name": name, "credentials": creds})

return result
16 changes: 16 additions & 0 deletions src/dedalus_labs/lib/mcp/wire.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
# Helpers
"build_connection_record",
"collect_unique_connections",
"slug_to_connection_name",
]


Expand Down Expand Up @@ -326,6 +327,21 @@ def collect_unique_connections(servers: Sequence[MCPServerProtocol]) -> List[Any
return unique


def slug_to_connection_name(slug: str) -> str:
"""Derive the canonical connection name from a server slug.

Slugs use ``org/server`` format; connection names use dashes.

Args:
slug: Server slug, URL, or name string.

Returns:
Connection name with slashes replaced by dashes.

"""
return slug.replace("/", "-")


# ---------------------------------------------------------------------------
# Credential Matching
# ---------------------------------------------------------------------------
Expand Down
Loading