MCP server for tangled

architecture#

tangled platform overview#

tangled is a git collaboration platform built on the AT Protocol. it consists of:

components#

  • appview (tangled.org): web interface using traditional HTTP routes

    • handles OAuth authentication for browser users
    • serves HTML/CSS/JS for the UI
    • proxies git operations to knots
    • does NOT expose XRPC endpoints
  • knots (e.g., knot1.tangled.sh): git hosting servers

    • expose XRPC endpoints for git operations
    • host actual git repositories
    • handle git-upload-pack, git-receive-pack, etc.
  • PDS (Personal Data Server): AT Protocol user data storage

    • stores user's atproto records
    • repos stored in sh.tangled.repo collection
    • each repo record contains: name, knot, description, etc.

data flow#

  1. user creates repo on tangled.org
  2. appview writes repo record to user's PDS (sh.tangled.repo collection)
  3. repo record includes knot field indicating which knot hosts it
  4. git operations routed through appview to the appropriate knot

MCP server implementation#

resolution flow#

when a client calls list_repo_branches("@owner/repo"):

  1. normalize input: strip @ if present (@ownerowner)

  2. resolve handle to DID:

    • if already DID format: use as-is
    • otherwise: call com.atproto.identity.resolveHandle
    • result: did:plc:...
  3. query repo collection:

    • call com.atproto.repo.listRecords on owner's PDS
    • collection: sh.tangled.repo (NOT sh.tangled.repo.repo)
    • find record where name matches repo name
  4. extract knot:

    • get knot field from repo record
    • example: knot1.tangled.sh
  5. call knot XRPC:

    • construct URL: https://{knot}/xrpc/sh.tangled.repo.branches
    • params: {"repo": "{did}/{repo_name}", "limit": N}
    • auth: service token from com.atproto.server.getServiceAuth

authentication#

uses AT Protocol service auth:

  1. authenticate to user's PDS with handle/password
  2. call com.atproto.server.getServiceAuth with aud: did:web:tangled.org
  3. receive service token (60 second expiration)
  4. use token in Authorization: Bearer {token} header for XRPC calls

key implementation details#

  • collection name: sh.tangled.repo
  • knot resolution: dynamic based on repo record, not hardcoded
  • handle formats: both owner/repo and @owner/repo accepted
  • private implementation: resolution logic in _tangled/ package
  • public API: clean tool interface in server.py

error handling#

  • invalid format: ValueError with clear message
  • handle not found: ValueError from identity resolution
  • repo not found: ValueError after querying collection
  • XRPC errors: raised from httpx with status code