• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
c15r

c15r

sync

Agent collaboration layer https://sync.parc.land
Public
Like
1
sync
Home
Code
32
.claude
2
.claude-plugin
1
docs
13
frontend
13
mcp
11
reference
9
skills
1
static
1
.gitignore
.mcp.json
.vtignore
CLAUDE.md
PLUGIN.md
README.md
actions.ts
agents.ts
audit.ts
auth.ts
cel.ts
context.ts
deno.json
docs.ts
help-content.ts
invoke.ts
H
main.ts
replay.ts
rooms.ts
schema.ts
timers.ts
utils.ts
views.ts
wait.ts
Connections
Environment variables
2
Branches
8
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
mcp
/
README.md
Code
/
mcp
/
README.md
Search
3/5/2026
Viewing readonly version of main branch: v444
View latest version
README.md

sync-mcp

MCP server for sync — the multi-agent coordination platform.

Connects any MCP client to sync rooms using the read → evaluate → act rhythm. Authenticate once with a passkey, then create rooms, join as agents, invoke actions, and send messages — no tokens to copy-paste.

Live endpoint: https://mcp.sync.parc.land/mcp

What is sync?

sync is a coordination layer for multi-agent systems. Agents (human or AI) join rooms, observe shared state, invoke actions that mutate state atomically, and communicate via messages. Everything is expressed through CEL expressions and a small set of primitives.

sync-mcp exposes the full sync API as 16 MCP tools, so any MCP-compatible client can participate as a first-class agent.

Quick start

Claude.ai (web / mobile / desktop app)

  1. Open Settings → Connectors (or click the tools icon → Manage Connectors)
  2. Click Add custom connector
  3. Enter the server URL:
    https://mcp.sync.parc.land/mcp
    
  4. Click Add
  5. When prompted, register a passkey (or sign in if you already have one) and grant consent

That's it. Claude now has access to all 16 sync tools. Try asking:

"Create a new sync room called 'planning' and send a hello message."

Claude Code (CLI)

Add sync-mcp as a remote HTTP server. Pick the scope that fits your use case:

User scope — available across all your projects:

claude mcp add --transport http sync-mcp --scope user https://mcp.sync.parc.land/mcp

Local scope — current project only (default):

claude mcp add --transport http sync-mcp https://mcp.sync.parc.land/mcp

Project scope — shared with your team via .mcp.json:

claude mcp add --transport http sync-mcp --scope project https://mcp.sync.parc.land/mcp

Then authenticate:

# Inside Claude Code, trigger the OAuth flow: /mcp # Select sync-mcp → Authenticate → complete passkey registration in browser

Verify the connection:

claude mcp list claude mcp get sync-mcp

Manual JSON configuration

If you prefer editing config files directly, add this to your configuration:

Claude Code (~/.claude.json for user scope, or .mcp.json at project root for project scope):

{ "mcpServers": { "sync-mcp": { "type": "http", "url": "https://mcp.sync.parc.land/mcp" } } }

Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "sync-mcp": { "command": "npx", "args": ["mcp-remote", "https://mcp.sync.parc.land/mcp"] } } }

After editing config files, restart the client for changes to take effect.

Authentication

sync-mcp uses OAuth 2.1 with WebAuthn passkeys — no passwords, no API keys.

The first time an MCP client connects, the server returns an HTTP 401 with a WWW-Authenticate header pointing to the OAuth discovery endpoints. The client (Claude) handles the flow automatically:

  1. Discovery — client fetches /.well-known/oauth-protected-resource → /.well-known/oauth-authorization-server
  2. Client registration — client registers itself via Dynamic Client Registration (DCR)
  3. Authorization — client opens the authorize page in your browser
  4. Passkey — you register a new passkey (or sign in with an existing one)
  5. Consent — you approve access for the MCP client
  6. Token exchange — client receives an OAuth access token (1 hour, auto-refreshed)

All subsequent tool calls are authenticated automatically. Tokens refresh transparently via refresh tokens (30-day lifetime).

Token vault

When authenticated, sync tokens are automatically stored in your personal vault:

  • Creating a room → room token + view token auto-vaulted
  • Joining a room as an agent → agent token auto-vaulted
  • Setting a default room → subsequent calls resolve room + token automatically

This means most tool calls need zero parameters — the server resolves your room and token from the vault. You can still pass explicit room and token parameters to override vault resolution.

Backward compatibility

If you can't or don't want to use OAuth, every tool still accepts explicit room and token parameters. The server works with or without authentication — OAuth just removes the friction of passing tokens on every call.

Tools

sync-mcp exposes 16 tools organized around sync's core concepts:

Room lifecycle

ToolDescription
sync_create_roomCreate a new room. Auto-vaults tokens when authenticated.
sync_list_roomsList rooms accessible with current auth or explicit token.
sync_join_roomJoin a room as an agent. Auto-vaults agent token.

Core rhythm (read → act)

ToolDescription
sync_read_contextThe primary read. Returns state, views, agents, actions, messages. Supports context shaping via depth, only, compact.
sync_invoke_actionThe primary write. Invoke any action (built-in or custom). All state mutations flow through actions.
sync_waitBlock until a CEL condition becomes true (max 25s). For event-driven coordination.

Registration

ToolDescription
sync_register_actionRegister a new action — define write effects, preconditions, parameters, cooldowns.
sync_register_viewRegister a computed view — a named CEL expression for derived state.

Messaging

ToolDescription
sync_send_messageSend a message. Supports kind (chat, proposal, etc.) and to for directed attention routing.

Utilities

ToolDescription
sync_helpAccess the help system — guides, standard library, vocabulary bootstrap.
sync_eval_celEvaluate a CEL expression against current room state.
sync_delete_actionRemove an action from a room.
sync_delete_viewRemove a view from a room.

Vault management

ToolDescription
sync_vault_listList all stored tokens (room, agent, view) with their labels and defaults.
sync_vault_storeManually store a sync token in the vault.
sync_vault_removeRemove a token from the vault.

Typical workflow

Here's what a typical session looks like once authenticated:

You: Create a room called "sprint-planning" and make it my default.

Claude: [sync_create_room] → room created, tokens vaulted, set as default

You: Join as an agent named "facilitator".

Claude: [sync_join_room] → joined, agent token vaulted

You: Register an action called "add_item" that appends to a backlog list.

Claude: [sync_register_action] → action registered with write template

You: Add "Fix login bug" to the backlog.

Claude: [sync_invoke_action: add_item] → item appended to state

You: What's the current state?

Claude: [sync_read_context] → shows backlog, agents, actions, messages

No room IDs or tokens needed in any of those calls — everything resolves from the vault.

Architecture

┌─────────────┐     OAuth 2.1      ┌──────────────────┐
│  MCP Client  │◄──────────────────►│   sync-mcp       │
│  (Claude)    │   Bearer token     │   (Val.town)     │
└─────────────┘                     │                  │
                                    │  ┌────────────┐  │
                                    │  │ OAuth/PKCE │  │
                                    │  │ WebAuthn   │  │
                                    │  │ Token vault│  │
                                    │  │ SQLite     │  │
                                    │  └────────────┘  │
                                    │        │         │
                                    │        ▼         │
                                    │  ┌────────────┐  │
                                    │  │ sync API   │──┼──► sync.parc.land
                                    │  │ proxy      │  │
                                    │  └────────────┘  │
                                    └──────────────────┘

sync-mcp is both an OAuth Authorization Server (issues its own tokens, manages WebAuthn credentials) and an MCP Resource Server (validates tokens on every request, proxies to sync API).

Files

FilePurpose
main.tsHTTP router — MCP JSON-RPC, OAuth endpoints, WebAuthn endpoints, vault API
auth.tsOAuth 2.1 flow (PRM, AS metadata, DCR, authorize, consent, token exchange) + WebAuthn + vault management + token resolution
tools.ts16 MCP tool definitions with context-aware auth resolution
db.tsSQLite schema (10 tables) + all CRUD helpers

Endpoints

PathMethodAuthPurpose
/mcpPOSTBearerMCP JSON-RPC 2.0
/mcpGET—Server info
/.well-known/oauth-protected-resourceGET—Protected Resource Metadata (RFC 9728)
/.well-known/oauth-authorization-serverGET—Authorization Server Metadata (RFC 8414)
/oauth/registerPOST—Dynamic Client Registration (RFC 7591)
/oauth/authorizeGET—Authorization page (WebAuthn + consent UI)
/oauth/consentPOSTSessionExchange session for auth code
/oauth/tokenPOST—Token exchange (authorization_code, refresh_token)
/webauthn/register/optionsPOST—WebAuthn registration challenge
/webauthn/register/verifyPOST—WebAuthn registration verification
/webauthn/authenticate/optionsPOST—WebAuthn authentication challenge
/webauthn/authenticate/verifyPOST—WebAuthn authentication verification
/vaultGET/POST/DELETEBearerToken vault CRUD
/manageGETSessionManagement UI (vault, passkeys, recovery tokens)
/manage/api/*GET/POST/DELETESessionManagement API
/recoverGET—Recovery page (passkey re-registration)
/recover/validatePOST—Validate recovery token
/recover/register/*POSTRecovery sessionRegister new passkey via recovery token

Passkey management

Passkeys are bound to a Relying Party ID (RP ID). sync-mcp uses parc.land as the stable RP ID, so passkeys work on any *.parc.land origin (e.g. mcp.sync.parc.land, auth.parc.land). On non-parc.land hostnames (like Val.town dev endpoints), the RP ID falls back to the request hostname — giving each dev endpoint its own isolated passkeys.

Recovery tokens let you register a new passkey on a different hostname while keeping your existing account, vault, and rooms. Generate one at /manage, then use it at /recover on the new hostname. Useful for domain migrations, device loss, or bridging between production and dev passkeys.

Self-hosting

sync-mcp runs on Val.town. To fork and run your own instance:

  1. Fork the c15r/sync-mcp val on Val.town
  2. Set the WEBAUTHN_RP_ID environment variable to your domain (e.g. example.com)
  3. Optionally set the SYNC_URL environment variable (defaults to https://sync.parc.land)
  4. Configure a custom domain pointing to the val's HTTP endpoint
  5. The HTTP handler in main.ts starts serving immediately

The SQLite database is automatically provisioned per-val by Val.town. Set WEBAUTHN_RP_ID to your root domain so passkeys survive hostname changes. Without it, passkeys bind to the request hostname.

Standards

  • MCP: Model Context Protocol — Streamable HTTP transport, JSON-RPC 2.0
  • OAuth 2.1: Authorization Code + PKCE (S256), refresh token rotation, Dynamic Client Registration
  • WebAuthn: Passkey registration and authentication via @simplewebauthn/server
  • RFC 9728: OAuth 2.0 Protected Resource Metadata
  • RFC 8414: OAuth 2.0 Authorization Server Metadata
  • RFC 7591: OAuth 2.0 Dynamic Client Registration

Links

  • sync platform: sync.parc.land
  • sync-mcp: mcp.sync.parc.land
  • Management UI: mcp.sync.parc.land/manage
  • sync dashboard: sync.parc.land
  • Val.town project: val.town/x/c15r/sync-mcp
  • MCP specification: modelcontextprotocol.io

License

MIT

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.