JustGo MCP server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@JustGo MCP serverIs Jo Bloggs's membership active, and which clubs is she in?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
JustGo MCP server
An MCP server that lets Claude, ChatGPT and other MCP clients look things up in a JustGo sports membership platform: members, their memberships and credentials (coaching and officiating qualifications, licences, with expiry dates), events and event bookings, and clubs and other organisations. With writes enabled, it can also change the dates of one member's membership. It is built from JustGo's public API documentation only: the OpenAPI 3.0.1 document "JustGo API" 2.2 at api.justgo.com/swagger/v2.2/swagger.json, shown in the Swagger UI at api.justgo.com/index.html. The spec has no servers block; the base URL https://api.justgo.com is inferred from where the spec is served.
Once it's connected, someone at a governing body or club can ask things like:
"Is Jo Bloggs's membership active, and which clubs is she in?"
"Which of Jo's coaching qualifications expire before the end of the year?"
"Which members are suspended?"
"What competitions are published, how many places are left on the Autumn Gala, and who has booked?"
"Which clubs in the South West hold the SwimMark accreditation, and when does it expire?"
With writes enabled: "Extend Jo's Adult Competitive membership to 31 March 2027."
Tools
Tool | What it does | API calls |
| Search members with every filter the endpoint documents: |
|
| One member with their memberships, organisations (with roles), credentials, event bookings and linked family members. |
|
| Memberships held by members: name, category, classification, type, status, start and end dates, membership number, owner. Filters |
|
| Credentials held by members: name, type, status, reference number, start and end (expiry) dates. Filters |
|
| Events with dates, booking deadline, venue, category, status, organiser, details and stages. Filters |
|
| One event with its tickets (price, booked, remaining places), promoters and stages. |
|
| Bookings (the API calls them candidates): who booked which ticket, booking status and dates. Filters |
|
| Clubs and other organisations: number, type, status, town, region, country, website, join link. Filters |
|
| One organisation with its awards (organisation credentials, granted and expiry dates) and memberships. |
|
| Changes the start and/or end date of one member's membership. Reads the membership first, sends the date that was not given unchanged, refuses locally when the end would be before the start, and returns the previous dates so the change can be reverted. Only registered when writes are enabled. |
|
The list tools take page (default 1), page_size (1 to 100, default 50) and max_pages (default 2). The page size stays fixed within a call so page numbers line up; when more remains, the result says which page to continue from. If the API applies a smaller page size than the one asked for, the result reports it as page_size_applied.
Not covered on purpose: every other write (creating or updating members, suspending members, adding members to clubs, creating credentials, memberships, events, stages, promoters and bookings, deleting anything), profile image upload, Members/LogInCheck, Members/PasswordReset and Members/ChangePassword (end users' passwords), competitions and rankings, shops and orders, rewards links, the /Schema endpoints, credential and membership definitions, and organisation-level credentials and memberships.
Related MCP server: Amiqus MCP server
Setup
Requires Node 18 or later.
npm install
npm run buildYou need the API secret JustGo issues for your organisation's account. The spec documents the exchange but not how the secret is issued: the "Published API" appears as a plan capability on justgo.com, so ask JustGo. The server posts the secret to POST /api/v2.2/Auth as {"secret": "..."} and sends the JWT it gets back as Authorization: Bearer … on every other request.
Claude Desktop: add this to claude_desktop_config.json:
{
"mcpServers": {
"justgo": {
"command": "node",
"args": ["/absolute/path/to/justgo-mcp/dist/index.js"],
"env": { "JUSTGO_SECRET": "your-secret" }
}
}
}Claude Code:
claude mcp add justgo -e JUSTGO_SECRET=your-secret -- node /absolute/path/to/justgo-mcp/dist/index.jsVariable | Required | Meaning |
| yes | The API secret, exchanged at |
| no |
|
| no | Defaults to |
Safety defaults
Read-only unless
JUSTGO_ALLOW_WRITES=true. The nine read tools carry the MCPreadOnlyHintannotation.update_membership_datesis markeddestructiveHint: true(it overwrites the stored dates) andidempotentHint: true(repeating it with the same dates changes nothing further).Members of sports governing bodies and clubs include children, so by default a person (member, linked family member, booker, event promoter) is identified by ID, member number and name only. Email addresses, phone numbers, postal addresses, dates of birth, gender, login names, last-login times and parents' names and emails are only returned when a tool is called with
include_contact_details=true. A club's email, phone number, street address, postcode and map position are treated the same way, because they are often a volunteer's own; its town, region, country, website and join link are returned. An event's venue address is returned by default: it is where the event takes place.Never returned, even on request: the untyped
additionalDetailsmember of members, events and organisations and the untypedoptinmember of members. The spec gives them no schema, and custom-form answers of this kind can hold medical, safeguarding, emergency-contact or consent information. When a record has them, the output lists their names undernot_returned, so the assistant can say the record holds more than it was shown. No file is ever downloaded, and no bank, card or payment data is requested: none of the endpoints used returns it.In free text, email addresses are replaced with
[email redacted]and phone-number-like sequences with[phone redacted]. In people's names (members, linked family members, bookers, promoters), event and course names and details, venue and location text, stage names and descriptions, and the organisation names shown by the organisation and event tools this is the default, and the raw text is returned withinclude_contact_details. Some free text is always redacted, even on request: the names of memberships, credentials, tickets, awards and club memberships, the names of the organisations on a member's record, the roles of club members and event promoters, linked family members' references, and JustGo's own error messages. The phone match is a heuristic: it covers international numbers written with+or00, with or without a bracketed trunk prefix or area code (+44 (0)7700 …,+1 (555) 123-4567,+61 (02) 9876 5432), numbers with a bracketed UK or North American area code such as(020) 7946 0958or(555) 123-4567, and UK-style0…numbers of 9 to 11 digits with spaces, dots or hyphens between groups. Other digit strings starting with0are redacted too, while UUIDs, numeric IDs, timestamps and hyphenated references are left alone. Credential reference numbers, ticket codes, award and club-membership references and websites are structured values and are returned unredacted. Note that afind_memberssearch on an email address still confirms that the address is registered, even though it is not shown.The secret and the JWT are never written to a log or an error message; if JustGo ever echoed the secret or the current token in an error, it would be replaced with
[redacted]. From an error response only the documented JSON fields (message, and theerrorsanddetailsmaps) are passed on; a non-JSON body (a gateway page, a login page) is never quoted.Arguments are checked before any call. An argument a tool does not declare (a misspelt or invented filter such as
first_nameorlastName) is refused with its name, so it never turns into an unfiltered search. Every ID on the endpoints used is typedformat: uuidin the spec, so only UUIDs are accepted; the one exception islist_events'sorganisation_id, which the spec types as a plain string of up to 500 characters and which is passed as given. String filters use the spec'smaxLengthwhere it gives one; where it gives none (SuspendStatus,EventNumber, and the membershipStatus,Category,ClassificationandOwnerType), 500 characters is this server's own cap.modified_after/modified_beforeare typeddate-timein the spec: a date-time with seconds and a time zone (2026-09-01T00:00:00Z,2026-09-01T10:30:00+01:00) is sent as given, a bare date (2026-09-01) is sent as midnight UTC that day (2026-09-01T00:00:00Z), and a date-time without seconds or a time zone is refused rather than guessed; impossible dates such as 2026-02-30 are refused. The dates forupdate_membership_datesmust be full date-times with seconds and a time zone, for the same reason.JustGo documents no rate limit: neither the spec nor the Swagger UI says anything about one. Requests are spaced 250 ms apart (about four per second). A 429 is retried at most twice for any method, on the assumption that a rate-limited request was not processed, waiting for
Retry-After(whole or fractional seconds, or an HTTP-date; 2 s then 4 s when the header is absent or unreadable). Each wait is capped at 10 seconds; if JustGo asks for a longer wait the call gives up at once and the message says how long to wait. A tool call that makes several requests (pages, lookups) can still run past the MCP client's default 60-second request timeout.502, 503 and 504 are retried the same way for
GETand forPOST /Auth(asking for a token again changes nothing). When all three attempts fail the error says the service may be unavailable. The membershipPUTis never retried after a gateway error, because it may already have been applied; the error says to check the membership first.The JWT is cached. If its
expclaim is present (read, not verified), a new one is fetched a minute before it expires (or halfway through its remaining life when that is under two minutes); withoutexpit is kept until the API answers 401. On a 401 the server fetches one fresh JWT and retries once; if that is refused too, the message says to check that the secret is still active.A 200 whose body is not a JSON object is reported as an error naming
JUSTGO_BASE_URL, never as an empty list. A get-by-ID that answers 200 without a record is reported as not found.
Tests
npm testThe suite builds the server and runs test/e2e.mjs (32 checks, about 40 seconds):
Validates every fixture record against the component schemas in JustGo's published spec (
MemberListV2_2Dto,MemberV2_2Dto,MemberMembershipListDtoV2_2,MemberSingleMembershipDtoV2_2,MemberCredentialDtoV2_2,EventResponseDtoListV2_2,EventDtoSingleV2_2,EventCandidateDtoV2_2,ClubDtoV2_2,ClubSingleDtoV2_2and everything they embed) with Ajv andajv-formats. Every one of these schemas setsadditionalProperties: false, so a fixture key the spec does not declare fails; negative controls prove an undeclared key and a malformed UUID are rejected. One deliberate loosening: OpenAPI 3.0 allowsnullable: truewithout a type, which Ajv refuses, so on the spec's eleven untyped members (theadditionalDetails,optin,additionalDataand onedatamember) that marker is dropped and they are validated as "any value". The spec is saved asspec.jsonand downloaded fromapi.justgo.com/swagger/v2.2/swagger.jsonon the first run when missing. The spec has no examples, so the fixture values are invented; only their shape comes from the spec. It then checks the built redaction helper on UK, international and North American phone forms (and that UUIDs, timestamps and references are left alone), that a dotted string such asapi.justgo.comor2.2.0is not taken for a JWT, and when a cached JWT is replaced for a givenexp(a minute early, or halfway through when under two minutes remain).Starts a local mock of the API:
POST /api/v2.2/Authtaking{ secret }and returning a JWT built at run time (401 for a wrong secret, 400 for an empty one),Bearerchecks on every other route with 401 for an unknown token, the documentedPageNumber/PageSizepaging withpageNumber,pageSize,totalPagesandtotalRecords(each of the last three can be left out, and the page size capped, to test the fallbacks), 400 for aModifiedAfter/ModifiedBeforethat is not an RFC 3339 date-time, the documented single-record envelope{ statusCode, message, object, data }, 400 in the documentedHttp400BadRequestResponseshape for a malformed ID, 404 in theHttp404NotFoundResponseshape for an unknown one, a one-off 429 withRetry-After, and it records every request (method, path, query, headers, body). The mock's list, detail, update, 400, 401 (in theHttp401UnAuthorizedResponseshape, which the spec documents for 403) and 404 responses are validated against the schemas the spec names for each operation. One mock answer is deliberately outside the spec: a get-by-ID answering 200 withdata: null, to test the server's handling of an unknown ID in that form; the suite asserts that this answer does not match the documented schema.Drives the built server over stdio with the official MCP client: tools/list and annotations; writes absent with
JUSTGO_ALLOW_WRITESunset orfalse; the token request in its documented form, without anAuthorizationheader, with the JWT reused across calls; paging across pages 1, 2 and 3 with a full last page, stopping attotalPageswith no fourth request, with requests at least 250 ms apart; withouttotalPages, stopping oncetotalRecordsrecords are fetched, following a smaller page size the API applies (reported inpageSizeor not), and withouttotalRecordseither, stopping at a short page or after an empty one; continuation fromnext_page; every documented filter of all six list tools passed through under its documented name and value, with bare dates sent as midnight-UTC date-times; redaction of contact details, dates of birth, addresses and parents' details by default and their return on request; emails and phone numbers typed into a member's first or last name, a linked family member's name, a booker's name and a promoter's role redacted by default (the role even on request);additionalDetailsandoptincontent never returned, even on request; club contact details and promoters' contacts only on request; emails and phone numbers (including a+1 (555) …number) in event details and stage descriptions redacted; ID and date validation before any call, including date-times without seconds or a time zone and unknown or misspelt argument names; the not-found message for a 404 and for a 200 without a record; the membershipPUTpreceded by aGET, its body validated againstMemberLicensePutDto, the unchanged date carried over and the change visible afterwards; the local refusals (end before start, no stored date, nothing to change) with noPUTsent; a 429 on thePUTretried once and a 502 on thePUTnot retried; a 400's message anderrorspassed on with contact details redacted and the secret scrubbed, and the current JWT scrubbed when a message echoes it; the 403 message; a revoked JWT replaced once on 401 and a persistent 401 reported without a loop; the JWT found in a text, JSON-string or JSON-object/Authresponse, including one whose envelope also holds dotted strings such asapi.justgo.com, and a response without one reported by its keys only; a 429 and a 502 from/Authretried; two parallel first calls sharing one token request; a JWT refreshed from itsexpclaim and one withoutexpreused; the 429 retry waiting forRetry-Afterin the seconds, fractional-seconds and HTTP-date forms, giving up after three attempts on a persistent 429 and at once on a wait above the cap; a 502 retried forGET; three 503s reported with advice and without the gateway HTML; a non-JSON 200 reported as an error; a wrong secret reported with a message namingJUSTGO_SECRETand not repeating it; and, as the last check, that every request the MCP servers made during the run used a documented method, path and query parameter names, with a JWT the mock issued asBeareron every call except/Auth.
The mock applies only some filters to its data (LastName, Email, memberNumber, MemberId, Status, EventCategory, EventId, BookingStatus, Type, OrganisationId, and the modified dates on members, credentials, events and organisations); for the others the suite checks that they reach the API exactly as documented, not what JustGo does with them.
Status
This is a working prototype. It has not been run against the live API, because it was built without a JustGo account (JustGo offers no trial; the API is a plan capability). Everything below comes from the published spec and should be confirmed on a real account:
The
/Authresponse. The spec documents only "200 Success" with no body, so the server looks for a JWT (the whole body, or a string inside a JSON object'sdatamember or at its top level, members named liketokenfirst) and only accepts a value whose first segment decodes to a JWT header with analg. Which form JustGo uses, whether the JWT carriesexp, how long it lasts, and what a wrong secret gets (the mock answers 401; during research an empty secret got 400 from the live API) are unconfirmed.How the secret is issued, what it can see (one organisation or a whole governing body) and when the API answers 403.
Paging: that
PageNumberis 1-based (assumed), the default and maximumPageSize(the server sends at most 100, its own cap), thatpageSize,totalPagesandtotalRecordsare always filled (the spec lists them but marks none required), and what a page past the end returns. WithouttotalPagesthe server stops oncetotalRecordsrecords are accounted for, and without either at a page shorter than the page size. If the API applied a smaller page size than asked without reporting it inpageSize, the server infers it from a short page whiletotalRecordssays more follow; a call that starts past page 1 in that situation could stop early.What the API answers for an unknown ID. The spec documents no 404 for these endpoints (only
GET /Events/{eventId}/Promotershas one); the server handles a 404 and a 200 without a record, and a 400 is passed on with JustGo's message.Filter semantics: whether
LastName,Email,MembershipandMembershipNamematch exactly or partially, the allowed values ofStatus,Category,Classification,OwnerType,SuspendStatus,BookingStatus,TypeandEventSubcategory(the spec lists none), whetherModifiedAfter/ModifiedBeforeare inclusive and whether the API reads them in UTC (the server sends a bare date as midnight UTC, which is an hour off UK local midnight in summer), and whetherlist_events'sOrganisationIdtakes a UUID or an organisation number (it is typed as a plain string).The sort order of every list. The spec documents none; the server returns whatever order the API uses.
Date formats. The spec types dates as
dateordate-time; the fixtures use2026-08-01and2026-08-01T09:00:00Z. If the live API emits date-times without a time zone (common for .NET services) or dates of birth as date-times, the server passes them through unchanged, but the suite's schema check would fail on such values.Which fields the live API actually fills, and what
additionalDetailsandoptincontain. The server never returns either.PUT /Memberships/Member/{membershipId}: whether bothstartDateandendDateare required (the server always sends both), how the time zone is read, whether the change triggers emails, renewals, payments or status changes in JustGo, whetherapplication/jsonis accepted (the spec lists it alongsideapplication/json-patch+json), and what the 201 body contains (the spec saysHttp200UpdateResponse).The wording of JustGo's error messages and whether any of them echo request data; the texts in the mock are its own, because the spec has no examples.
A 429 is retried for the
PUTtoo, on the assumption that a rate-limited request was not applied; JustGo documents no 429 at all.How many requests per second the API tolerates; nothing is documented, so the 250 ms spacing is a guess on the polite side.
Going to production
This version runs locally over stdio with the organisation's own API secret. For governing bodies and clubs to connect from claude.ai or ChatGPT without handling secrets, the next step is a remote server (Streamable HTTP) behind OAuth, hosted by JustGo, so each user's own permissions apply, and then a listing in the Claude and ChatGPT connector directories. Further write tools (suspensions, credential updates, bookings) can follow once they can be tested on a real account.
Licence
MIT. Built by Alexandru Dragoș (alexandru.dragos96@gmail.com) with an AI agent (Claude) working under his direction.
Available Tools
9 toolsfind_membersFind membersARead-only
Search members with JustGo's documented member filters (email, member number, login ID, last name, organisation, credential, event, membership, suspension status, modified dates). Returns ID, member number, name, member status and suspension level; contact details, date of birth, address and parents' details only with include_contact_details. Note that a match on an email filter still confirms that such an address is registered, even though the address itself is not shown.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page to start from (1 is the first page; use next_page from a previous call to continue) | |
| No | Email (exact value passed as Email) | ||
| event_id | No | Members linked to this event (EventId) | |
| login_id | No | Login ID (LoginId) | |
| last_name | No | Last name (LastName) | |
| max_pages | No | How many pages to fetch in this call | |
| page_size | No | Records per page (1-100) | |
| membership | No | Membership name (Membership) | |
| credential_id | No | Members holding this credential (CredentialId) | |
| member_number | No | Member number (memberNumber) | |
| modified_after | No | Only records modified after this date-time (ModifiedAfter). A bare date is sent as midnight UTC that day. | |
| suspend_status | No | Suspension status (SuspendStatus); allowed values are not documented | |
| modified_before | No | Only records modified before this date-time (ModifiedBefore). A bare date is sent as midnight UTC that day. | |
| organisation_id | No | Members of this organisation (OrganisationId) | |
| include_contact_details | No | Include email, phone, address, date of birth, gender, login name, last login and parents' details, and stop redacting emails and phone numbers from names |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds real behavioral context beyond them – which fields are returned by default, that contact/DOB/address/parents data is gated behind include_contact_details, and the subtle redaction rule that an email filter match still proves the address is registered even when hidden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the search scope before the return-shape and redaction caveats. The long parenthetical filter list is dense but each clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 15-parameter, no-required-args search tool with no output schema, the description covers the filter surface, the default return fields, and the contact-detail opt-in. Pagination behavior is left entirely to the well-documented page/max_pages/page_size schema fields, which is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description's filter list largely mirrors parameters the schema already documents (email, member_number, login_id, organisation_id, etc.) and its include_contact_details sentence restates the schema's own wording, adding little new parameter-level meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Search members') and enumerates the filter dimensions and returned fields, so the agent knows exactly what the tool retrieves. It does not explicitly contrast itself with the singular sibling get_member, so sibling differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: search by the documented filters, and set include_contact_details when contact data is needed. There is no explicit statement of when to prefer this over get_member or the list_* siblings, nor any exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventGet eventARead-only
One event with its tickets (price, places booked and remaining), promoters (names and roles; contact details only on request) and stages.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event ID (UUID, from list_events) | |
| include_contact_details | No | Include promoters' email addresses and phone numbers, and stop redacting emails and phone numbers from free text |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=true), so the description's value is in disclosing the return shape and the privacy behavior: promoter contact details are withheld by default and surfaced only on request. That default-redaction behavior is a genuinely useful trait beyond the annotations, though it stops short of describing error behavior for a missing/invalid event.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence that front-loads the resource and then enumerates the payload; every clause earns its place and nothing is padded or repeated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly takes on the burden of describing what comes back (tickets, promoters, stages) and the default redaction behavior, which is enough for an agent to call it correctly. Minor gaps remain around error handling for an unknown event_id and whether the caller needs specific permissions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters, including the UUID pattern and the fact that include_contact_details also un-redacts free text. The description's 'contact details only on request' is a less precise restatement of that, adding no syntax or semantic detail the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (a single event) and enumerates its sub-parts: tickets with price/places booked/remaining, promoters with names and roles, and stages. That is far more informative than a bare 'get event' and implicitly contrasts with the list-oriented siblings, though it never explicitly frames itself as the fetch-by-ID counterpart to list_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The singular 'One event' implies this is for a single-record lookup versus list_events, and 'contact details only on request' hints at when to set the flag, but there is no explicit when-to-use, no named alternative, and no statement of prerequisites (e.g. that event_id must come from list_events).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_memberGet memberARead-only
One member with their memberships, organisations (with roles), credentials, event bookings and linked family members. Names and statuses by default; contact details, date of birth, address and parents' details only with include_contact_details. Free-form additional details and opt-in answers are never returned.
| Name | Required | Description | Default |
|---|---|---|---|
| member_id | Yes | Member ID (UUID, from find_members) | |
| include_contact_details | No | Include the member's and linked family members' contact details and dates of birth, and bookers' emails |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint/openWorldHint, but the description adds the response-composition contract: names and statuses by default, contact details/DOB/address/parents' details gated behind include_contact_details, and free-form additional details and opt-in answers never returned. That tells the agent exactly what it will and will not get back, which is exactly what annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with what is returned, then the opt-in toggle, then the never-returned exclusions. No filler and no repetition of the schema's field list.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the full burden of describing the response shape, and it does so by enumerating returned aggregates and default/gated/never-returned fields. With only two parameters, both covered in the schema, nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description extends include_contact_details beyond the schema's wording by adding address and parents' details to the gated set. It also indirectly reinforces member_id's role by pairing 'One member' with a single-member lookup.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource ('One member') plus an explicit inventory of the aggregates returned: memberships, organisations with roles, credentials, event bookings and linked family members. This scope statement lets an agent distinguish it from list_member_memberships, list_member_credentials and find_members without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the agent can infer it should call this for a single member's consolidated profile, and the description clarifies when contact data appears. But no alternative is named (find_members for lookup, list_member_* for narrow slices), so tool routing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_organisationGet organisationBRead-only
One club or organisation with its awards (organisation credentials, with granted and expiry dates) and memberships.
| Name | Required | Description | Default |
|---|---|---|---|
| organisation_id | Yes | Organisation ID (UUID, from list_organisations) | |
| include_contact_details | No | Include email, phone, street address, postcode and map position |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds that awards carry granted and expiry dates and that memberships are included, which is useful content-level context, but it says nothing about error behavior for unknown IDs or how the contact-details flag changes the payload.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with no filler, front-loading the resource identity before the returned sub-resources. It is a fragment rather than a complete clause, which costs it the top score but keeps it efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must convey the return shape, and it does so partially (awards, memberships, credential dates) while omitting the organisation's own scalar fields and the effect of include_contact_details. For a read-only tool whose annotations and 100%-covered schema carry the rest, this is adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both organisation_id (UUID sourced from list_organisations) and include_contact_details are already documented in the schema. The description adds no parameter-level detail beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the resource precisely ('one club or organisation') and enumerates what is bundled with it (awards/credentials with granted and expiry dates, plus memberships), which cleanly distinguishes it from the sibling list_organisations. It is written as a noun phrase rather than a verb+resource, so the retrieval action is only implied by the name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus list_organisations, get_member, or list_member_credentials. An agent must infer from the name that this fetches a single record by ID; no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_event_bookingsList event bookingsARead-only
Bookings (candidates) on events: who booked which ticket, booking status and dates. Names by default, email addresses only with include_contact_details.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page to start from (1 is the first page; use next_page from a previous call to continue) | |
| category | No | Event category (Category) | |
| event_id | No | Only bookings on this event (EventId) | |
| max_pages | No | How many pages to fetch in this call | |
| page_size | No | Records per page (1-100) | |
| sub_category | No | Event sub-category (SubCategory) | |
| booking_status | No | Booking status (BookingStatus) | |
| modified_after | No | Only records modified after this date-time (ModifiedAfter). A bare date is sent as midnight UTC that day. | |
| modified_before | No | Only records modified before this date-time (ModifiedBefore). A bare date is sent as midnight UTC that day. | |
| include_contact_details | No | Include bookers' email addresses and stop redacting emails and phone numbers from names |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds genuinely useful behavior beyond that: outputs are redacted to names by default, and email addresses only appear when include_contact_details is set. It does not mention pagination defaults or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The returned content is front-loaded and the privacy condition follows, so the most important scoping fact is not buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter listing tool with no output schema, the description covers output contents, the mapping of bookers to tickets, and the default redaction behavior. Missing pagination expectations (max_pages default of 2) and result ordering, but these are largely documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all ten parameters are already documented in the schema, including the redaction behavior of include_contact_details. The description restates that flag's effect but adds no syntax, format, or interaction detail beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (bookings/candidates on events) and enumerates the returned fields: booker, ticket, status, dates. It is immediately distinguishable from the sibling tools, which cover organisations, members, and events, though it does not explicitly contrast itself with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to pick this tool over an alternative, no stated prerequisites, and no exclusions. The only conditional statement concerns include_contact_details, which is parameter behavior rather than usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsList eventsCRead-only
Events (courses, competitions and the like) with dates, booking deadline, venue, category, status, organiser and stages, filtered with the documented parameters.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page to start from (1 is the first page; use next_page from a previous call to continue) | |
| status | No | Event status (Status) | |
| category | No | Event category (EventCategory) | |
| max_pages | No | How many pages to fetch in this call | |
| page_size | No | Records per page (1-100) | |
| event_number | No | Event number (EventNumber) | |
| sub_category | No | Event sub-category (EventSubcategory) | |
| modified_after | No | Only records modified after this date-time (ModifiedAfter). A bare date is sent as midnight UTC that day. | |
| modified_before | No | Only records modified before this date-time (ModifiedBefore). A bare date is sent as midnight UTC that day. | |
| organisation_id | No | Organisation (OrganisationId; typed as a plain string in the spec) | |
| include_contact_details | No | Stop redacting emails and phone numbers from event names, details, venue text and stage descriptions |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds nothing behavioral beyond that: it does not mention pagination via next_page, the multi-page batching (max_pages), or the fact that contact details are redacted by default unless include_contact_details is set.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single front-loaded sentence with the resource stated first, which is good, but the trailing clause 'filtered with the documented parameters' is pure filler that could be cut without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter list tool with no output schema, enumerating the returned fields is genuinely useful. But it omits the pagination/continuation model and the default-redaction behavior that an agent must reason about, leaving gaps that the schema descriptions only partially close.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 11 parameters, including the date semantics for modified_after/before and the redaction behavior of include_contact_details. The description adds no parameter-level meaning beyond 'the documented parameters', so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (events/courses/competitions) and enumerates the fields it exposes (dates, deadline, venue, category, status, organiser, stages), so an agent knows what data comes back. However, the verb is only implied via the tool name, and it never distinguishes itself from the sibling get_event (single-record fetch), so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no mention of the alternative get_event, and no statement of prerequisites. The phrase 'filtered with the documented parameters' is circular and tells the agent nothing it cannot already see in the schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_member_credentialsList member credentialsARead-only
Credentials held by members, such as coaching or officiating qualifications and licences, with status, reference number, start date and end (expiry) date. Pass member_id for one member's credentials.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page to start from (1 is the first page; use next_page from a previous call to continue) | |
| status | No | Credential status (Status) | |
| category | No | Category (Category) | |
| max_pages | No | How many pages to fetch in this call | |
| member_id | No | Only this member's credentials (MemberId) | |
| page_size | No | Records per page (1-100) | |
| definition_id | No | Credential definition (DefinitionId) | |
| modified_after | No | Only records modified after this date-time (ModifiedAfter). A bare date is sent as midnight UTC that day. | |
| modified_before | No | Only records modified before this date-time (ModifiedBefore). A bare date is sent as midnight UTC that day. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description usefully adds what a credential record contains (status, reference number, start/end dates), which partially compensates for the missing output schema, but says nothing about pagination behaviour (page/max_pages/page_size) or the scale of results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler. The resource definition and its field content come first, and the scoping hint is front-loaded at the end where it is easy to act on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description's enumeration of record fields is the right kind of compensation, and all 9 input parameters are fully documented in the schema. The remaining gap is behavioural: nothing tells the agent that results are paged and that next_page/max_pages govern multi-call retrieval.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% across all 9 parameters, including patterns, bounds and defaults, so the schema carries the semantics. The description only echoes member_id and implies the returned fields; it adds no format or filtering syntax beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the resource precisely ('credentials held by members') and enumerates the content of each record (status, reference number, start/end dates), which is more than a restatement of the title. It does not explicitly contrast itself with the closest sibling (list_member_memberships), but the resource noun is distinct enough that an agent will not confuse them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Pass member_id for one member's credentials' is a concrete usage instruction for the scoped case, which is more than implied guidance. However, there is no when-not guidance, no mention of how the status/category/definition_id/modified_* filters should be combined, and no alternatives named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_member_membershipsList member membershipsARead-only
Memberships held by members (name, category, classification, status, start and end dates, owning organisation), filtered with the documented parameters. Pass member_id for one member's memberships.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page to start from (1 is the first page; use next_page from a previous call to continue) | |
| status | No | Membership status (Status) | |
| category | No | Category (Category) | |
| owner_id | No | Owning organisation (OwnerId) | |
| max_pages | No | How many pages to fetch in this call | |
| member_id | No | Only this member's memberships (MemberId) | |
| page_size | No | Records per page (1-100) | |
| owner_type | No | Owner type (OwnerType) | |
| definition_id | No | Membership definition (DefinitionId) | |
| classification | No | Classification (Classification) | |
| modified_after | No | Only records modified after this date-time (ModifiedAfter). A bare date is sent as midnight UTC that day. | |
| modified_before | No | Only records modified before this date-time (ModifiedBefore). A bare date is sent as midnight UTC that day. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safe-read profile is covered. The description adds the set of returned fields, useful given there is no output schema, but says nothing about pagination behavior (page/max_pages interplay), auth requirements, or rate limits beyond what the schema states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the resource and its returned fields, with the member_id hint last. The parenthetical field list is long but earns its place because no output schema exists; 'filtered with the documented parameters' is the only mildly vacuous phrase.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 12 optional parameters and no output schema, the description compensates by listing the returned fields and the key scoping parameter. Pagination semantics (page, page_size, max_pages) are left entirely to the schema, which is acceptable since the schema documents them, but a note on continuation would round it out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented in the schema, including the page/next_page continuation pattern. The description only calls out member_id and the filterable field list, adding marginal meaning beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (memberships held by members) and enumerates the fields returned, which is concrete and distinguishable from siblings like list_member_credentials or get_member. It stops short of explicitly contrasting itself with those siblings, but the resource is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It offers one actionable usage hint — pass member_id to scope to a single member — and mentions filtering via 'the documented parameters.' There is no explicit when-to-use-this-vs-an-alternative guidance (e.g., versus get_member or find_members), so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_organisationsList organisationsARead-only
Clubs and other organisations with number, type, status, town, region, website and join link. Email, phone, street address, postcode and map position only with include_contact_details (a club's contact details are often a volunteer's own).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page to start from (1 is the first page; use next_page from a previous call to continue) | |
| type | No | Organisation type (Type) | |
| status | No | Status (Status) | |
| max_pages | No | How many pages to fetch in this call | |
| page_size | No | Records per page (1-100) | |
| credential_id | No | Organisations holding this credential (CredentialId) | |
| modified_after | No | Only records modified after this date-time (ModifiedAfter). A bare date is sent as midnight UTC that day. | |
| membership_name | No | Membership name (MembershipName) | |
| modified_before | No | Only records modified before this date-time (ModifiedBefore). A bare date is sent as midnight UTC that day. | |
| organisation_id | No | One organisation (OrganisationId) | |
| organisation_number | No | Organisation number (OrganisationNumber) | |
| include_contact_details | No | Include email, phone, street address, postcode and map position |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description adds real value beyond that: it states contact fields are withheld by default and explains why (a club's contact details are often a volunteer's own), which is a privacy behavior an agent would not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero filler: the first states default fields, the second states the conditional contact fields and the reason. Information is front-loaded and each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter, no-output-schema read tool, the description covers return content and the opt-in privacy gate, and pagination is fully documented in the schema. It is slightly incomplete in not hinting at how the many filters combine, but nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description reinforces include_contact_details' effect and rationale, but it adds little for the eleven filter/pagination parameters, which the schema already documents adequately.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (clubs and other organisations) and enumerates the fields returned, which clearly separates it from the singular get_organisation sibling. It never uses an explicit verb like 'list/retrieve', relying on the name and field inventory to convey purpose, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus get_organisation or find_members, and no hint about the filter parameters (type, status, organisation_number) for narrowing results. The only conditional guidance concerns include_contact_details, which is parameter-level rather than usage-level.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.1.0- First observed
find_members - First observed
get_event - First observed
get_member - First observed
get_organisation - First observed
list_event_bookings - First observed
list_events - First observed
list_member_credentials - First observed
list_member_memberships - First observed
list_organisations
TDQS
Scored across 9 tools
Each tool targets a distinct resource (organisations, members, memberships, credentials, events, bookings) with clear list/get or search semantics. Minor overlap risk between find_members and list_member_memberships/list_member_credentials, but the descriptions distinguish member records from their sub-resources.
Strong verb_noun pattern throughout (list_organisations, get_organisation, list_events, get_event, list_event_bookings) with consistent British spelling. The only deviation is find_members, which uses 'find' instead of the otherwise uniform list/get verbs.
Nine tools is well-scoped for a domain spanning organisations, members, memberships, credentials, events and bookings. Each tool earns its place by covering a distinct entity or sub-resource, with no redundant entries.
Good read coverage: list+get for organisations, members and events, plus list for memberships, credentials and bookings. Minor gaps exist (no get for memberships/credentials/bookings and no write operations), but the surface appears intentionally read-oriented and supports core discovery workflows.
Maintenance
Related MCP Connectors
Let AI agents query data and act across all your business apps via MCP.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Manage SRG+ hubs, channels, content, assets, users, and workspaces from any MCP-aware AI agent.
Create forms, read submissions, and build invitations from Claude, ChatGPT, or any MCP client.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables MCP clients like Claude and ChatGPT to query and manage TicketSource box office data, including events, performances, bookings, customers, and seats, through natural language.7MIT
- AlicenseAqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read an Amiqus ID account—clients, onboarding records and steps, check results, templates, case status counts and webhooks—and, when writes are enabled, create records.9MIT
- AlicenseAqualityCmaintenanceEnables MCP clients such as Claude and ChatGPT to read events, performances, seating, packages, visits, transactions, and organisation context from a ticketing channel, and, when writes are enabled, create and release reservations.10MIT
- AlicenseNot gradedqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read practice-management data including organization, clinicians, diaries, availability, bookings, patients, invoices, payments, staff tasks, services, and locations, and optionally create staff tasks, create bookings, and cancel bookings.MIT