Koskamo

Goblin Gains MCP

An MCP server that integrates Goblin Gains' coached workout library into AI assistants. It allows users to request, vary, or invent conditioning workouts based on available equipment and time, with results linked back to the app for logging.

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.

Goblin Gains MCP logo, by Goblin GainsVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by Goblin Gains
MCP endpoint (Streamable HTTP)
https://api.goblingains.com/mcp
Vendor documentation

What you can do with it

  • Suggest a 20-minute workout with specific equipment
  • Generate a Hyrox session for two people
  • Invent a new 15-minute workout with a pull-up bar

Source and maintenance

Vendor evidenceRegistry 1.0.0

Protocol and capabilities

Server
goblin-workouts 1.30.0
MCP protocol
2025-06-18
Tools
7 advertised
Resources
0 advertised
Resource templates
0 advertised
Prompts
0 advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  },
  "prompts": {
    "listChanged": false
  },
  "resources": {
    "subscribe": false,
    "listChanged": false
  },
  "experimental": {}
}

Server-provided instructions

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

Goblin Gains makes conditioning workouts (CrossFit, Hyrox, engine work) from its own generator, without AI. Use these tools instead of writing workouts yourself. Which tool: - suggest_workouts: workouts for an ask (minutes, equipment, movements, an archetype from list_archetypes), close to proven library workouts. - vary_workout: variations of one library workout by name ("Fran"), in its format or another. - generate_workouts: brand-new workouts unlike any in the library, for one person. Before generating: when the user names equipment, call list_equipment and pass its keys or plain names, with "1 dumbbell" when there is only one. Movements the user wants or bans go through find_movements first. Say who trains (sex, people) when the user said so. Show each workout as returned, its save link too: the link saves it in the Goblin Gains app. When the user says a workout is wrong, bad or good, send it with report_workout.

Tools

7 advertised

list_archetypes
Advertised by the server during the last successful anonymous check.
Advertised read-only

The workout archetypes the generator makes, one per line: key, name, formats, minutes, line count, and the session slots it serves.

list_archetypes input schema
{
  "type": "object",
  "title": "list_archetypesArguments",
  "properties": {
    "style": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Style",
      "default": null,
      "description": "Keep only one style's archetypes: crossfit, hyrox or hybrid; all when omitted. Example: \"hyrox\"."
    }
  }
}
list_archetypes output schema
{
  "type": "object",
  "title": "list_archetypesOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
list_archetypes annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_equipment
Advertised by the server during the last successful anonymous check.
Advertised read-only

The equipment suggest_workouts' `equipment` takes, one per line: key: name, with "(machine)" on ergometers (rower, ski erg, bikes). Keys, names and common names ("echo", "row erg", "DB", "kb") all work.

list_equipment input schema
{
  "type": "object",
  "title": "list_equipmentArguments",
  "properties": {}
}
list_equipment output schema
{
  "type": "object",
  "title": "list_equipmentOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
list_equipment annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
find_movements
Advertised by the server during the last successful anonymous check.
Advertised read-only

Movement slugs whose name holds `query` (e.g. "row", "sled"), for suggest_workouts' include and exclude, machines and runs first.

find_movements input schema
{
  "type": "object",
  "title": "find_movementsArguments",
  "required": [
    "query"
  ],
  "properties": {
    "kind": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Kind",
      "default": null,
      "description": "Keep one movement kind only, one of strength, olympic, plyo, cyclic, carry, mobility (cyclic: row, ski, bike, run); all when omitted. Example: \"cyclic\"."
    },
    "query": {
      "type": "string",
      "title": "Query",
      "maxLength": 100,
      "description": "Text the movement name holds, any case. Example: \"sled\"."
    }
  }
}
find_movements output schema
{
  "type": "object",
  "title": "find_movementsOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
find_movements annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
suggest_workouts
Advertised by the server during the last successful anonymous check.
Advertised read-only

New workouts from our generator, as text. Ask this instead of writing workouts yourself. Nothing is saved. Example, two people with an echo bike, rower and ski erg, 40-60 min: suggest_workouts(count=5, people=2, minutes_min=40, minutes_max=60, equipment=["echo-bike", "row-ergometer", "ski-erg"], bodyweight=False) A shortfall says what blocked it.

suggest_workouts input schema
{
  "type": "object",
  "title": "suggest_workoutsArguments",
  "properties": {
    "sex": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Sex",
      "default": null,
      "description": "Who trains, for the weights and machine doses: \"men\", \"women\", or \"mixed\" (a man and a woman together: each at their own; Hyrox stations at the mixed doubles race load). Omitted when the user did not say: every line reads both, men's/women's (\"9/6 kg\", \"12/10 kcal\"). Anything but men gets only workouts with a women's weight on every loaded line. Example: \"women\"."
    },
    "only": {
      "type": "boolean",
      "title": "Only",
      "default": false,
      "description": "True: the workouts hold the included movements and nothing else (each may repeat). Needs include. Example: true."
    },
    "count": {
      "type": "integer",
      "title": "Count",
      "default": 3,
      "maximum": 5,
      "minimum": 1,
      "description": "How many workouts, at most 5; from 3 on, a mix of archetypes (at most 2 of one unless nothing else fits). Example: 3."
    },
    "people": {
      "type": "integer",
      "title": "People",
      "default": 1,
      "maximum": 20,
      "minimum": 1,
      "description": "How many train together with one of each machine. Above 1, only workouts they can share come back: partner workouts (taking turns on a station), or EMOMs/intervals with a different machine on every line and at least one line per person (start apart, rotate). Example: 2."
    },
    "exclude": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Exclude",
      "default": null,
      "description": "Movement slugs or names (from find_movements) every workout must leave out. Example: [\"burpees\"]."
    },
    "include": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Include",
      "default": null,
      "description": "Movement slugs or names (from find_movements) every workout must hold. Example: [\"wallballs\", \"sled-push\"]."
    },
    "partner": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "title": "Partner",
      "default": null,
      "description": "True: only partner workouts (two people share the work: turns at a station, or each on a station at once, then swap). False: none. Omitted: either. Example: true."
    },
    "archetype": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Archetype",
      "default": null,
      "description": "A key or name from list_archetypes; any when omitted. Example: \"A5\" or \"chipper\"."
    },
    "equipment": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Equipment",
      "default": null,
      "description": "What the athletes have, as list_equipment keys or names (\"echo-bike\" or \"echo\", \"row erg\", \"ski erg\"), one item per entry. Say \"1 dumbbell\" or \"1 kettlebell\" when there is only one: movements needing a pair (farmers carry, dumbbell bench press) are left out. Other counts are ignored (\"1 echo\" is the echo bike): say how many train in people. Movements needing anything else (a bench press needs a bench) are left out; runs need \"running\" in the list. A name matching several keys or none is an error naming them. Example: [\"1 dumbbell\", \"box\", \"ski-erg\"]. Omitted is a full gym."
    },
    "bodyweight": {
      "type": "boolean",
      "title": "Bodyweight",
      "default": true,
      "description": "False also leaves out movements needing no equipment (burpees, runs), so only the listed equipment is used. Example: false."
    },
    "cap_minutes": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 240,
          "minimum": 1
        },
        {
          "type": "null"
        }
      ],
      "title": "Cap Minutes",
      "default": null,
      "description": "A time cap the workout must fit, in whole minutes. Example: 30."
    },
    "minutes_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 240,
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "title": "Minutes Max",
      "default": null,
      "description": "Longest estimated workout length, in minutes. Example: 60."
    },
    "minutes_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 240,
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "title": "Minutes Min",
      "default": null,
      "description": "Shortest estimated workout length, in minutes. Example: 40."
    },
    "show_scores": {
      "type": "boolean",
      "title": "Show Scores",
      "default": true,
      "description": "True adds a line of scores under each workout: feasibility (0-100, can it be done as written), difficulty (0-100, the chance of not finishing inside the cap), and against the workout it was made from: stimulus (0-1, CrossFit's stimulus kept, with the levers changed), work (x the seed's), mix shift (how far the work moved between movement patterns), design (0-1) and, for Hyrox workouts, race fidelity (0-1). Example: false."
    },
    "temperature": {
      "type": "number",
      "title": "Temperature",
      "default": 0,
      "description": "0 to 1. 0: the same ask always brings the same workouts. Above 0: other ones each call, the higher the further from the library workouts they vary (0.3 close variations, 1 far ones). Example: 0.3."
    }
  }
}
suggest_workouts output schema
{
  "type": "object",
  "title": "suggest_workoutsOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
suggest_workouts annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
vary_workout
Advertised by the server during the last successful anonymous check.
Advertised read-only

Variations of one library workout from our generator (no AI), as text, in its own format or another. Nothing is saved. A shortfall says what blocked it.

vary_workout input schema
{
  "type": "object",
  "title": "vary_workoutArguments",
  "required": [
    "name"
  ],
  "properties": {
    "sex": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Sex",
      "default": null,
      "description": "Who trains, for the weights and machine doses: \"men\", \"women\", or \"mixed\" (a man and a woman together: each at their own; Hyrox stations at the mixed doubles race load). Omitted when the user did not say: every line reads both, men's/women's (\"9/6 kg\", \"12/10 kcal\"). Anything but men gets only workouts with a women's weight on every loaded line. Example: \"women\"."
    },
    "name": {
      "type": "string",
      "title": "Name",
      "maxLength": 100,
      "description": "The library workout's name or part of it, any case; several matches are an error listing them (up to 10) to ask again. Example: \"Fran\"."
    },
    "count": {
      "type": "integer",
      "title": "Count",
      "default": 3,
      "maximum": 5,
      "minimum": 1,
      "description": "How many variations, at most 5. Example: 3."
    },
    "format": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Format",
      "default": null,
      "description": "Turn it into this format first: for_time, amrap, emom, intervals. About its minutes: an EMOM gives each line its own minute when a round is over 40 s, intervals rest as long as a round's work. Omitted keeps its own. Example: \"emom\"."
    },
    "people": {
      "type": "integer",
      "title": "People",
      "default": 1,
      "maximum": 20,
      "minimum": 1,
      "description": "How many train together with one of each machine. Above 1, only workouts they can share come back: partner workouts (taking turns on a station), or EMOMs/intervals with a different machine on every line and at least one line per person (start apart, rotate). Example: 2."
    },
    "equipment": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Equipment",
      "default": null,
      "description": "What the athletes have, as list_equipment keys or names (\"echo-bike\" or \"echo\", \"row erg\", \"ski erg\"), one item per entry. Say \"1 dumbbell\" or \"1 kettlebell\" when there is only one: movements needing a pair (farmers carry, dumbbell bench press) are left out. Other counts are ignored (\"1 echo\" is the echo bike): say how many train in people. Movements needing anything else (a bench press needs a bench) are left out; runs need \"running\" in the list. A name matching several keys or none is an error naming them. Example: [\"1 dumbbell\", \"box\", \"ski-erg\"]. Omitted is the kit the workout already uses."
    },
    "bodyweight": {
      "type": "boolean",
      "title": "Bodyweight",
      "default": true,
      "description": "False also leaves out movements needing no equipment (burpees, runs), so only the listed equipment is used. Example: false."
    },
    "show_scores": {
      "type": "boolean",
      "title": "Show Scores",
      "default": true,
      "description": "True adds a line of scores under each workout: feasibility (0-100, can it be done as written), difficulty (0-100, the chance of not finishing inside the cap), and against the workout it was made from: stimulus (0-1, CrossFit's stimulus kept, with the levers changed), work (x the seed's), mix shift (how far the work moved between movement patterns), design (0-1) and, for Hyrox workouts, race fidelity (0-1). Example: false."
    },
    "temperature": {
      "type": "number",
      "title": "Temperature",
      "default": 0.5,
      "description": "0 to 1, how far they stray from it (0.2 close, 1 far). Example: 0.5."
    }
  }
}
vary_workout output schema
{
  "type": "object",
  "title": "vary_workoutOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
vary_workout annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
generate_workouts
Advertised by the server during the last successful anonymous check.
Advertised read-only

New workouts unlike any in the library, from our generator (no AI), as text: evolved from the library's workouts and movements (more lines, fewer, other formats) into kinds it does not hold. For one person. Nothing is saved; other ones each call. suggest_workouts and vary_workout stay close to library workouts instead. A shortfall says what blocked it.

generate_workouts input schema
{
  "type": "object",
  "title": "generate_workoutsArguments",
  "properties": {
    "sex": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Sex",
      "default": null,
      "description": "Who trains, for the weights and machine doses: \"men\", \"women\", or \"mixed\" (a man and a woman together: each at their own; Hyrox stations at the mixed doubles race load). Omitted when the user did not say: every line reads both, men's/women's (\"9/6 kg\", \"12/10 kcal\"). Anything but men gets only workouts with a women's weight on every loaded line. Example: \"women\"."
    },
    "count": {
      "type": "integer",
      "title": "Count",
      "default": 3,
      "maximum": 5,
      "minimum": 1,
      "description": "How many workouts, at most 5. Example: 3."
    },
    "format": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Format",
      "default": null,
      "description": "Only this format: for_time, amrap, emom, intervals. Any when omitted. Example: \"amrap\"."
    },
    "exclude": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Exclude",
      "default": null,
      "description": "Movement slugs or names (from find_movements) every workout must leave out. Example: [\"burpees\"]."
    },
    "include": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Include",
      "default": null,
      "description": "Movement slugs or names (from find_movements) every workout must hold; fewer come back the more are named. Example: [\"wallballs\"]."
    },
    "equipment": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "maxItems": 30
        },
        {
          "type": "null"
        }
      ],
      "title": "Equipment",
      "default": null,
      "description": "What the athletes have, as list_equipment keys or names (\"echo-bike\" or \"echo\", \"row erg\", \"ski erg\"), one item per entry. Say \"1 dumbbell\" or \"1 kettlebell\" when there is only one: movements needing a pair (farmers carry, dumbbell bench press) are left out. Other counts are ignored (\"1 echo\" is the echo bike): say how many train in people. Movements needing anything else (a bench press needs a bench) are left out; runs need \"running\" in the list. A name matching several keys or none is an error naming them. Example: [\"1 dumbbell\", \"box\", \"ski-erg\"]. Omitted is a full gym."
    },
    "bodyweight": {
      "type": "boolean",
      "title": "Bodyweight",
      "default": true,
      "description": "False also leaves out movements needing no equipment (burpees, runs), so only the listed equipment is used. Example: false."
    },
    "minutes_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 240,
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "title": "Minutes Max",
      "default": null,
      "description": "Longest estimated workout length, in minutes. Example: 25."
    },
    "minutes_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 240,
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "title": "Minutes Min",
      "default": null,
      "description": "Shortest estimated workout length, in minutes. Example: 10."
    },
    "show_scores": {
      "type": "boolean",
      "title": "Show Scores",
      "default": true,
      "description": "True adds a line of scores under each workout: feasibility (0-100, can it be done as written), difficulty (0-100, the chance of not finishing inside the cap), and against the workout it was made from: stimulus (0-1, CrossFit's stimulus kept, with the levers changed), work (x the seed's), mix shift (how far the work moved between movement patterns), design (0-1) and, for Hyrox workouts, race fidelity (0-1). Example: false."
    }
  }
}
generate_workouts output schema
{
  "type": "object",
  "title": "generate_workoutsOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
generate_workouts annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
report_workout
Advertised by the server during the last successful anonymous check.

Send Goblin Gains what the user thinks of a workout from these tools. Call it whenever the user points out a mistake (wrong equipment, a weight, a dose that cannot fit) or says a workout is bad or good: the words go to Goblin Gains, nothing else about the user does.

report_workout input schema
{
  "type": "object",
  "title": "report_workoutArguments",
  "required": [
    "note",
    "verdict"
  ],
  "properties": {
    "note": {
      "type": "string",
      "title": "Note",
      "maxLength": 2000,
      "minLength": 1,
      "description": "What the user said about the workout, in their words. Example: \"Farmers carry needs two dumbbells; I said I have one.\""
    },
    "verdict": {
      "type": "string",
      "title": "Verdict",
      "maxLength": 100,
      "description": "One of mistake, bad, good: \"mistake\" (something in it is wrong), \"bad\" (it works but is a poor workout), \"good\". Example: \"mistake\"."
    },
    "workout": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 100
        },
        {
          "type": "null"
        }
      ],
      "title": "Workout",
      "default": null,
      "description": "The workout's save link from suggest_workouts, vary_workout or generate_workouts, or its id; omitted for the tools as a whole. Example: \"https://app.goblingains.com/w/<id>\"."
    }
  }
}
report_workout output schema
{
  "type": "object",
  "title": "report_workoutOutput",
  "required": [
    "result"
  ],
  "properties": {
    "result": {
      "type": "string",
      "title": "Result"
    }
  }
}
report_workout annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}

Prompts

0 advertised

No prompt definitions available.

Resources

0 advertised

No resource definitions available.

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
1215 ms
95th percentile latency
1215 ms

Maintenance history

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

  • · probe · passed · 1215 ms · metadata changed · 7 tool(s), 0 resource(s), 0 resource template(s), 0 prompt(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 goblin-gains-mcp https://api.goblingains.com/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 goblin-gains-mcp --url https://api.goblingains.com/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable goblin-gains-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "goblin-gains-mcp": {
      "url": "https://api.goblingains.com/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "goblin-gains-mcp": {
      "type": "streamableHttp",
      "url": "https://api.goblingains.com/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start goblin-gains-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "goblin-gains-mcp": {
      "type": "http",
      "url": "https://api.goblingains.com/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 goblin-gains-mcp https://api.goblingains.com/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": {
    "goblin-gains-mcp": {
      "url": "https://api.goblingains.com/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": {
    "goblin-gains-mcp": {
      "serverUrl": "https://api.goblingains.com/mcp"
    }
  }
}

Let your agent find its tools

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

Do you run Goblin Gains MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing