Koskamo

Pairloop Doubles Mixer MCP

A community MCP server for generating rotating partner schedules for social doubles sports like pickleball, tennis, padel, and badminton. It balances rests, handles partner constraints, and exports schedules to PDF, CSV, and JSON formats for agents to manage event logistics.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Pairloop Doubles Mixer MCP logo, by ZovoCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-01Published by Zovo
MCP endpoint (Streamable HTTP)
https://doubles-mixer.zovo.one/mcp
Vendor documentation

What you can do with it

  • Generate rotating partner schedules for 4 to 48 players
  • Print court sheets and score individual standings
  • Balance rests and report unused courts
  • Download schedules in PDF, CSV, and JSON formats

Source and maintenance

Community listingRegistry 1.0.0

Protocol and capabilities

Server
doubles-mixer 1.0.0
MCP protocol
2025-06-18
Tools
3 advertised
Resources
1 advertised
Resource templates
1 advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "resources": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Make social doubles schedules for individual players who rotate partners. Return the compact schedule_request so standings can regenerate the same matches. The full indexed schedule is in the widget and JSON download. Use the reported partner-repeat gap honestly: general bounded search may not reach the counting lower bound. Unscored games remain pending. Do not use for fixed-team brackets, ratings, or governing tournament rules.

Tools

3 advertised

generate_mixer_schedule — Generate rotating doubles schedule
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants a pickleball round robin generator, pickleball mixer, rotating partners schedule, tennis mixer schedule or padel americano. Makes balanced rests, partner rotations, a fairness summary, printable PDF score sheets and CSV for 4 to 48 players, 1 to 12 courts and 1 to 24 rounds. Does not balance ratings or make fixed-team brackets; bounded optimization can leave partner repeats above the lower bound.

generate_mixer_schedule input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "players",
    "courts",
    "rounds"
  ],
  "properties": {
    "seed": {
      "type": "number",
      "description": "Repeatable seed, a whole number from 0 to 4294967295, e.g. 42. Defaults to 1; four players in one round enumerate ordered rotations before repeating (24 without groups, 16 with groups). Larger configurations use seeded bounded search."
    },
    "paper": {
      "enum": [
        "letter",
        "a4"
      ],
      "type": "string",
      "description": "Print sheet size, e.g. \"letter\" (US Letter, default) or \"a4\"."
    },
    "courts": {
      "type": "number",
      "description": "Available courts, a whole number from 1 to 12, e.g. 2. Unfillable courts are left unused."
    },
    "rounds": {
      "type": "number",
      "description": "Number of rounds, a whole number from 1 to 24, e.g. 7."
    },
    "group_a": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 160,
        "description": "Player name, up to 40 characters, e.g. Alex."
      },
      "maxItems": 46,
      "description": "Optional group A names, e.g. [\"Alex\",\"Blair\"]. Supply both groups; each player must be in one group."
    },
    "group_b": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 160,
        "description": "Player name, up to 40 characters, e.g. Alex."
      },
      "maxItems": 46,
      "description": "Optional group B names, e.g. [\"Casey\",\"Drew\"]. Partners cross groups; unequal groups may be refused if balanced rests are impossible."
    },
    "players": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 160,
        "description": "Player name, up to 40 characters, e.g. Alex."
      },
      "maxItems": 48,
      "description": "4 to 48 distinct player names, e.g. [\"Alex\",\"Blair\",\"Casey\",\"Drew\"]. Names are limited to 40 characters."
    }
  }
}
generate_mixer_schedule output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "kind",
    "summary",
    "details"
  ],
  "properties": {
    "kind": {
      "type": "string"
    },
    "details": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "summary": {
      "type": "string"
    },
    "downloads": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "string"
      }
    }
  },
  "additionalProperties": false
}
generate_mixer_schedule annotations
{
  "title": "Generate rotating doubles schedule",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
score_mixer_standings — Score individual mixer standings
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants individual standings from a social doubles schedule and game scores. Counts wins, losses, draws, points for, points against, difference and win percent for up to 48 players and 288 scores. Accepts a generated schedule_request or an indexed schedule; unscored games stay pending. Does not use rating systems or governing tournament rules.

score_mixer_standings input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "schedule",
    "scores"
  ],
  "properties": {
    "scores": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "round",
          "court",
          "score_a",
          "score_b"
        ],
        "properties": {
          "court": {
            "type": "number",
            "description": "Court number, e.g. 1."
          },
          "round": {
            "type": "number",
            "description": "Round number, e.g. 1."
          },
          "score_a": {
            "type": "number",
            "description": "Team A points, a whole number 0 to 999, e.g. 11."
          },
          "score_b": {
            "type": "number",
            "description": "Team B points, a whole number 0 to 999, e.g. 7."
          }
        }
      },
      "maxItems": 288,
      "description": "Game scores, e.g. [{round:1,court:1,score_a:11,score_b:7}]. Ties count as draws; supply at least one score."
    },
    "schedule": {
      "anyOf": [
        {
          "type": "object",
          "required": [
            "players",
            "courts",
            "rounds"
          ],
          "properties": {
            "seed": {
              "type": "number",
              "description": "Repeatable seed, a whole number from 0 to 4294967295, e.g. 42. Defaults to 1; four players in one round enumerate ordered rotations before repeating (24 without groups, 16 with groups). Larger configurations use seeded bounded search."
            },
            "courts": {
              "type": "number",
              "description": "Available courts, a whole number from 1 to 12, e.g. 2. Unfillable courts are left unused."
            },
            "rounds": {
              "type": "number",
              "description": "Number of rounds, a whole number from 1 to 24, e.g. 7."
            },
            "group_a": {
              "type": "array",
              "items": {
                "type": "string",
                "maxLength": 160,
                "description": "Player name, up to 40 characters, e.g. Alex."
              },
              "maxItems": 46,
              "description": "Optional group A names, e.g. [\"Alex\",\"Blair\"]. Supply both groups; each player must be in one group."
            },
            "group_b": {
              "type": "array",
              "items": {
                "type": "string",
                "maxLength": 160,
                "description": "Player name, up to 40 characters, e.g. Alex."
              },
              "maxItems": 46,
              "description": "Optional group B names, e.g. [\"Casey\",\"Drew\"]. Partners cross groups; unequal groups may be refused if balanced rests are impossible."
            },
            "players": {
              "type": "array",
              "items": {
                "type": "string",
                "maxLength": 160,
                "description": "Player name, up to 40 characters, e.g. Alex."
              },
              "maxItems": 48,
              "description": "4 to 48 distinct player names, e.g. [\"Alex\",\"Blair\",\"Casey\",\"Drew\"]. Names are limited to 40 characters."
            }
          }
        },
        {
          "type": "object",
          "required": [
            "players",
            "rounds"
          ],
          "properties": {
            "rounds": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "round",
                  "matches"
                ],
                "properties": {
                  "round": {
                    "type": "number",
                    "description": "Round number, e.g. 1."
                  },
                  "matches": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "court",
                        "team_a",
                        "team_b"
                      ],
                      "properties": {
                        "court": {
                          "type": "number",
                          "description": "Court number, e.g. 1."
                        },
                        "team_a": {
                          "type": "array",
                          "items": {
                            "type": "number",
                            "description": "Zero-based player index, e.g. 0 for the first player."
                          },
                          "maxItems": 2,
                          "description": "Team A player indexes, e.g. [0,1]."
                        },
                        "team_b": {
                          "type": "array",
                          "items": {
                            "type": "number",
                            "description": "Zero-based player index, e.g. 0 for the first player."
                          },
                          "maxItems": 2,
                          "description": "Team B player indexes, e.g. [2,3]."
                        }
                      }
                    },
                    "maxItems": 12,
                    "description": "Doubles matches, e.g. [{court:1,team_a:[0,1],team_b:[2,3]}]."
                  },
                  "sit_out": {
                    "type": "array",
                    "items": {
                      "type": "number",
                      "description": "Zero-based player index, e.g. 0 for the first player."
                    },
                    "maxItems": 48,
                    "description": "Indexes sitting out, e.g. [4]. Omit to calculate from matches."
                  }
                }
              },
              "maxItems": 24,
              "description": "The schedule rounds, e.g. one round with one court."
            },
            "players": {
              "type": "array",
              "items": {
                "type": "string",
                "maxLength": 160,
                "description": "Player name, up to 40 characters, e.g. Alex."
              },
              "maxItems": 48,
              "description": "4 to 48 distinct player names, e.g. [\"Alex\",\"Blair\",\"Casey\",\"Drew\"]. Names are limited to 40 characters."
            }
          }
        }
      ],
      "description": "The returned schedule_request, e.g. {players:[\"Alex\",\"Blair\",\"Casey\",\"Drew\"],courts:1,rounds:3,seed:42}, or a full indexed schedule JSON."
    }
  }
}
score_mixer_standings output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "kind",
    "summary",
    "details"
  ],
  "properties": {
    "kind": {
      "type": "string"
    },
    "details": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "summary": {
      "type": "string"
    },
    "downloads": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "string"
      }
    }
  },
  "additionalProperties": false
}
score_mixer_standings annotations
{
  "title": "Score individual mixer standings",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}
check_mixer_fairness — Check mixer fairness limits
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants to check social doubles schedule limits before making a rotating partners schedule. Reports usable courts, balanced sit-out totals, unavoidable consecutive rests and a counting lower bound on partner repeats for 4 to 48 players and 1 to 24 rounds. Does not claim that bounded scheduling reaches the lower bound or balance player ratings.

check_mixer_fairness input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "players",
    "courts",
    "rounds"
  ],
  "properties": {
    "seed": {
      "type": "number",
      "description": "Repeatable seed, a whole number from 0 to 4294967295, e.g. 42. Defaults to 1; four players in one round enumerate ordered rotations before repeating (24 without groups, 16 with groups). Larger configurations use seeded bounded search."
    },
    "courts": {
      "type": "number",
      "description": "Available courts, a whole number from 1 to 12, e.g. 2. Unfillable courts are left unused."
    },
    "rounds": {
      "type": "number",
      "description": "Number of rounds, a whole number from 1 to 24, e.g. 7."
    },
    "group_a": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 160,
        "description": "Player name, up to 40 characters, e.g. Alex."
      },
      "maxItems": 46,
      "description": "Optional group A names, e.g. [\"Alex\",\"Blair\"]. Supply both groups; each player must be in one group."
    },
    "group_b": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 160,
        "description": "Player name, up to 40 characters, e.g. Alex."
      },
      "maxItems": 46,
      "description": "Optional group B names, e.g. [\"Casey\",\"Drew\"]. Partners cross groups; unequal groups may be refused if balanced rests are impossible."
    },
    "players": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 160,
        "description": "Player name, up to 40 characters, e.g. Alex."
      },
      "maxItems": 48,
      "description": "4 to 48 distinct player names, e.g. [\"Alex\",\"Blair\",\"Casey\",\"Drew\"]. Names are limited to 40 characters."
    }
  }
}
check_mixer_fairness output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "kind",
    "summary",
    "details"
  ],
  "properties": {
    "kind": {
      "type": "string"
    },
    "details": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "summary": {
      "type": "string"
    },
    "downloads": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "string"
      }
    }
  },
  "additionalProperties": false
}
check_mixer_fairness annotations
{
  "title": "Check mixer fairness limits",
  "readOnlyHint": true,
  "openWorldHint": false,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

1 advertised

doubles-mixer-widget — Pairloop Doubles Mixer view

Advertised by the server during the last successful anonymous check.

Interactive view for Pairloop Doubles Mixer.

doubles-mixer-widget URI
ui://widget/doubles-mixer-v7-1.0.0-5777a4b9043cd5df6239c0c486014d6b1ce02c46e442ddcf0c5e4d7cc7b468dd.html

MIME type: text/html;profile=mcp-app

doubles-mixer-widget-legacy — Pairloop Doubles Mixer view (previous versions)

Advertised by the server during the last successful anonymous check.

doubles-mixer-widget-legacy URI template
ui://widget/doubles-mixer-{version}.html

MIME type: text/html;profile=mcp-app

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
624 ms
95th percentile latency
624 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 624 ms · metadata changed · 3 tool(s), 1 resource(s), 1 resource template(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http pairloop-doubles-mixer-mcp https://doubles-mixer.zovo.one/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add pairloop-doubles-mixer-mcp --url https://doubles-mixer.zovo.one/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable pairloop-doubles-mixer-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "pairloop-doubles-mixer-mcp": {
      "url": "https://doubles-mixer.zovo.one/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "pairloop-doubles-mixer-mcp": {
      "type": "streamableHttp",
      "url": "https://doubles-mixer.zovo.one/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start pairloop-doubles-mixer-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "pairloop-doubles-mixer-mcp": {
      "type": "http",
      "url": "https://doubles-mixer.zovo.one/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http pairloop-doubles-mixer-mcp https://doubles-mixer.zovo.one/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "pairloop-doubles-mixer-mcp": {
      "url": "https://doubles-mixer.zovo.one/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "pairloop-doubles-mixer-mcp": {
      "serverUrl": "https://doubles-mixer.zovo.one/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Pairloop Doubles Mixer MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.