---
title: "Connect to the Sign Customiser MCP Server"
description: "Endpoint, OAuth discovery URLs, scopes, client configuration and a first call for the Sign Customiser MCP server. Written for agents and the people building them."
url: "https://www.signcustomiser.com/mcp/connect/"
lastModified: "2026-08-25"
---

# Connect to the Sign Customiser MCP server

Sign Customiser is the platform sign makers use to sell custom signs online. This server exposes one merchant's store: its customisers, the option families and pricing they sell at, and the products, orders and quotes around them. Everything below is fact, in the order a client needs it.

## At a glance

- Endpoint https://web.signcustomiser.com/mcp
- Transport Streamable HTTP
- Method POST, with Accept: application/json, text/event-stream
- Protocol revisions 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05
- Authorization OAuth 2.1, authorization code with PKCE S256
- Dynamic client registration Available, RFC 7591, public clients only
- Tools 39, or 44 with the mcp:advanced scope
- Tenancy One token is bound to one store for its whole life

## Discovery

An unauthenticated request to the endpoint answers with the pointer that starts discovery:

```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://web.signcustomiser.com/.well-known/oauth-protected-resource/mcp"
```

- `https://web.signcustomiser.com/.well-known/oauth-protected-resource/mcp` RFC 9728 protected-resource metadata. Also served at /.well-known/oauth-protected-resource with the same document.
- `https://web.signcustomiser.com/.well-known/oauth-authorization-server` RFC 8414 authorization-server metadata. Also served at /.well-known/oauth-authorization-server/mcp.
- `https://web.signcustomiser.com/oauth/register` RFC 7591 dynamic client registration. No secret is issued or accepted. Redirect URIs must be HTTPS or loopback HTTP, matched exactly.
- `https://web.signcustomiser.com/oauth/authorize` Authorization endpoint. PKCE S256 is mandatory. Send resource=https://web.signcustomiser.com/mcp per RFC 8707.
- `https://web.signcustomiser.com/oauth/token` Token endpoint. Grants: authorization\_code, refresh\_token. Access tokens last 60 minutes, refresh tokens 30 days and rotate on use.
- `https://web.signcustomiser.com/oauth/revoke` RFC 7009 revocation. Authenticate with the client\_id the token was issued to.

The authorization response carries no RFC 9207 `iss` parameter, so take issuer assurance from discovery. A token is bound to one store, and the binding survives refresh rotation. Nothing a client sends can change which store it acts for.

## Scopes

Request the smallest set that covers the work. A tool whose scope the merchant declined answers with an `insufficient_scope` error naming what it needed, rather than failing quietly.

- `customisers:read` Read customisers and every option family they own.
- `customisers:write` Create and change customisers and their option records.
- `pricing:read` Read a customiser's pricing document and pricing model.
- `pricing:write` Replace or merge a customiser's pricing document.
- `products:read` Read products created from a customiser.
- `products:write` Record integration products against a customiser.
- `orders:read` Read orders and their design, production and delivery details.
- `orders:write` Create orders. An order can reach a manufacturer.
- `quotes:read` Read quote and custom-design submissions.
- `webhooks:read` Read webhook subscriptions and available event types.
- `webhooks:write` Create, change and delete webhook subscriptions.
- `store:read` Read the store record, its subscription and its granted scopes.
- `analytics:read` Read the order and revenue summary.
- `mcp:advanced` Reveal the five advanced catalogue tools. Grants no data on its own; each operation still needs the scope above that matches it.

## Client configuration

Claude Code:

```bash
claude mcp add --transport http sign-customiser https://web.signcustomiser.com/mcp
```

Run `/mcp` afterwards and choose Authenticate to complete the browser consent step.

Cursor, and any other client that reads an `mcp.json`. In Cursor that is `.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` globally:

```json
{
  "mcpServers": {
    "sign-customiser": {
      "type": "http",
      "url": "https://web.signcustomiser.com/mcp"
    }
  }
}
```

Clients that infer the transport from the URL ignore `"type"`. Leave it in; it is harmless where it is not needed.

Codex, in `~/.codex/config.toml`:

```toml
[mcp_servers.sign_customiser]
url = "https://web.signcustomiser.com/mcp"
```

Claude on the web and Claude Desktop: **Settings > Connectors > Add custom connector**, then paste the endpoint URL. ChatGPT: **Settings > Connectors**, add a custom connector with the endpoint URL. Developer mode is required while a connector is unlisted.

MCP Inspector: run `npx @modelcontextprotocol/inspector`, connect with transport Streamable HTTP, and leave `protocolEra` at `legacy`. This server answers the `initialize` family of revisions and does not answer the 2026-07-28 `server/discover` family, so a run configured with `modern` fails to negotiate by design.

## First call

List the tools the connection can see:

```bash
curl -sS https://web.signcustomiser.com/mcp \
  -H "Authorization: Bearer $SIGN_CUSTOMISER_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Then identify the store. `get_store` takes no arguments, needs `store:read`, and reports which scopes the merchant approved, which is the cheapest way to find out what the rest of the session can do:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_store",
    "arguments": {}
  }
}
```

The result:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Connected to the universal store \"Demo Signs\" (id 12)."
      }
    ],
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": { "id": 12, "name": "Demo Signs" },
      "id": 12,
      "name": "Demo Signs",
      "platform": "universal",
      "plan": "starter",
      "currency": "GBP",
      "integrations": [
        {
          "object": "integration",
          "id": 17,
          "type": "custom",
          "name": "Warehouse bridge",
          "enabled": true
        }
      ],
      "scopes": ["store:read", "customisers:read"],
      "created_at": "2026-01-12T03:14:15Z"
    },
    "isError": false
  }
}
```

Every tool returns `structuredContent` alongside the text summary, and every result carries the `request_id` and the `store` it acted on. List tools return an opaque cursor; pass it back unchanged rather than building one.

## Write conventions

- Reads and writes are separate tools. Nothing changes a store unless its name says so.
- Every write that supports it takes `dry_run: true` and returns the same validation verdict without applying anything. Call it that way first.
- Deletions, order creation and product creation require `confirm: true` and an `idempotency_key`. A replayed key returns the original result with `idempotent_replay: true`.
- Prices are integer minor units with an explicit currency. Sizes are centimetres.
- Start from `list_customisers` to get an integer customiser id. Every other customiser tool needs one. Read an option family with `list_customiser_options` before writing to it.

## Errors

- `401` The response carries a resource\_metadata challenge. No token, an expired token, or a token bound to another resource. Run discovery from the challenge URL and re-authorise.
- `invalid_target` An authorization request whose resource parameter named an API other than this one. Send resource=https://web.signcustomiser.com/mcp, or omit it.
- `insufficient_scope` A tool result, not a protocol error. The connection is valid; the merchant did not approve the permission that tool needs. Read required\_scopes from the error and ask the merchant to reconnect and approve it. Do not retry.
- `-32602` An argument failed the tool's input schema. Read the argument name from the message and correct it.
- `429` The endpoint's own rate limit. Wait for retry\_after.

## Reference

- [`mcp-tools.json`](/help/mcp-tools.json) Every tool with its scope, annotations, input and output schema, error cases and wire-shape examples. One file, generated from the running server.
- [`/help/mcp/`](/help/mcp/) The tool reference. One page per tool at /help/mcp/tools/<tool\_name>/, each with a .md alternate at the same path plus .md.
- [`/help/mcp/guides/connect/`](/help/mcp/guides/connect/) Per-client setup, what the merchant approves, and how a connection is revoked.
- [`/help/mcp/guides/authentication/`](/help/mcp/guides/authentication/) Discovery, dynamic registration, PKCE, resource binding, token lifetimes, revocation.
- [`/help/mcp/guides/advanced-catalogue/`](/help/mcp/guides/advanced-catalogue/) search\_operations and the four executors that reach the rest of the platform API under mcp:advanced.
- [`/help/mcp/guides/code-mode/`](/help/mcp/guides/code-mode/) Generating typed code against the tool schemas instead of calling tools one at a time.
- [`/help/llms.txt`](/help/llms.txt) The documentation index in plain text. /help/llms-full.txt is the whole corpus in one file.

Using an assistant rather than building one? [The MCP server overview](/mcp/) explains what a connection can do and how a merchant approves it.