# unulu

> AI agent website builder. Create and publish link-in-bio sites via MCP or REST API.

- name: ai.unulu/unulu
- version: 0.1.0
- connection class: R0 (autonomous)
- trust: 81/100
- quality: 82/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/ai.unulu%2Funulu
- tools: https://api.protogrid.dev/v1/servers/ai.unulu%2Funulu/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "unulu": {
      "type": "http",
      "url": "https://mcp.unulu.ai"
    }
  }
}
```


## Trust

- hygiene: 100
- liveness: 98
- freshness: 45
- provenance: 75
- drivers: +repository +dns-namespace +reachable +uptime-96% -stale-228d
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 82/100 (good)

### protocol: 75 (weight 25)

- warn `protocol.modern`: newest supported version is 2025-03-26; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
- n/a `protocol.stateless`: only applies to 2026-07-28 servers
- pass `protocol.transport`: streamable HTTP
- n/a `protocol.list_ttl`: only applies to 2026-07-28 servers

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 79 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 1 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 4 of 4 tools declare readOnlyHint or destructiveHint
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: unulu_create_site (idempotentHint); unulu_get_state (idempotentHint); unulu_update_site (idempotentHint); …
- pass `tools.token_cost`: about 2,090 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 100 (weight 15)

- pass `stability.changes`: no tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 4, about 2,090 tokens to load them all
- tool set hash: 9e4fc140e7bc1aa9c88082d02b772986
- badge: [![protogrid quality](https://protogrid.dev/badge/ai.unulu/unulu.svg)](https://protogrid.dev/servers/ai.unulu/unulu)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

_No tool definition changes recorded._

## Remotes

- https://mcp.unulu.ai (streamable-http, auth none, reachable true, uptime30d 0.95652175)

## Packages

_none_

## Tools (4)

- `unulu_check_handle`: Check whether a handle is available on unu.lu (not other platforms like Instagram, TikTok, etc.). For example, checking 'joe' tells you if joe.unu.lu is available for claiming. Use this to help users choose a handle before they visit the claim page.
- `unulu_create_site`: Create a link-in-bio site with a name, bio, and links. Returns a live URL on unu.lu that expires in 1 hour unless claimed. Do NOT call until you have at least a name and one link from the user — gather real content first, never create with placeholder or empty content. If the user provides a handle (e.g. '_guy.a' for Instagram), construct the full URL yourself — do not ask them to paste it. When feasible, offer to find all public links for the person. Before calling: tell the user they can choose a skin on the preview page for the overall aesthetic; ask permission before adding emoji leading_icons to decorate links (for not-well-known social URLs). The response includes an assistant_message with the site URL and claim details — present these to the user. Persist claim_token and claim_code_short for subsequent updates — never ask the user for them back in the same conversation. Never create a duplicate site; always update the existing one. After creation: tell the user they can pick a custom handle when they claim; share the preview URL in a copy-paste block; offer to refine bio, links, or ordering. Keep iteration fast — apply changes immediately, don't re-confirm minor edits.
- `unulu_get_state`: Returns the current state of a site including its name, bio, links, and URL. No authentication required. If expires_at is absent, the site has been claimed and is permanent. Accepts a site ID, a full URL (e.g. https://abc123.unu.lu), or a bare hostname (e.g. abc123.unu.lu).
- `unulu_update_site`: Update an existing site. All fields are optional — only provided fields are changed. Links replace the entire array (omit to keep existing). Before updating, always call unulu_get_state first to read the current links and their ids — do not guess link ids. Authorization depends on site lifecycle: X-Claim-Token header for ephemeral (pre-claim) sites, X-Edit-Token header for claimed (post-claim) sites. If neither token is available and the site is claimed, use requestEditAccess to obtain an edit_token. If you created the site in this conversation, you already have the claim_token — use it directly. Returns the full updated site state. Keep iteration fast — apply changes immediately without re-confirming minor edits unless ambiguous. Accepts a site ID, a full URL (e.g. https://abc123.unu.lu), or a bare hostname (e.g. abc123.unu.lu).
