Reply in plain prose only: never draw images, cards, buttons or choice lists of your own — every card on screen already carries its portrait and its button. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face. Cupid is a four-scene interactive romance. On this host every scene is delivered inside one call to cupid-present-options — the narration and the dialogue in its fields, the player's choices beneath them — and the card is drawn above anything you write, so the scene lives in the card; a short line of your own may follow it, the scene itself never does. The fourth scene is delivered the same way; the goodbye that follows its click — or an early exit — ends with cupid-complete-game. Every setup card carries the button for its gate, so the whole game can be played by pressing.
Discoverability
1 of 6 checks17/100
Client listings and public setup information.
mcp.json or server-card.json
Either mcp.json or an MCP Server Card declaring this endpoint passes.
No matching manifest was found at /mcp.json or /.well-known/mcp.json.
All view resources are readable and use ui:// with a supported MCP Apps HTML MIME type
Tool invocation metadata present
8 tool(s) missing openai/toolInvocation metadata
How to fix: For tools that render a UI resource, add openai/toolInvocation with string fields invoking and invoked (present-tense labels shown while the tool runs and after it finishes, e.g. "Searching…" / "Searched").
How to fix: Use a ui:// URI and text/html;profile=mcp-app. For mcp-use v1, use widgetMetadata.metadata.widgetDescription; for v2, use the bound tool's view.description. The current description check reads _meta.ui.widgetDescription or _meta["openai/widgetDescription"] on resource contents or linked tools, not resource.description. Consequently, v2 view.description alone may leave this warning: report the checker compatibility gap instead of adding unsupported v1 fields or claiming the warning is fixed.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description81/100
Start a game of Cupid, an interactive rom-com: shows the home card with the cast of fictional characters to choose from and loads the game's voice and rules. Use when the user asks to play Cupid or start a new game.
Describe the returned information so the agent knows whether it will answer the request.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
{
"name": "cupid-start-game",
"title": "Start Cupid Game",
"description": "Start a game of Cupid, an interactive rom-com: shows the home card with the cast of fictional characters to choose from and loads the game's voice and rules. Use when the user asks to play Cupid or start a new game.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"mortals"
],
"properties": {
"mortals": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Present the fictional mortal character for the Cupid matchmaking game. Shows their zodiac-based personality. The player picks a mortal in the Home chooser ('I choose {Name} as my mortal') — pass `mortal="{Name}"` (the exact name). Never call it in the same turn as cupid-start-game: the chooser is on screen and the player hasn't picked yet. The tool echoes a `mortal_id` — thread it through the rest of the arc. After presenting, WAIT for user to say they're ready to meet the match. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face.
Describe the returned information so the agent knows whether it will answer the request.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
mortal
The chosen mortal's name (e.g. from 'I choose {Name} as my mortal.'). The server resolves the name to its character id. Always pass it — the player picks from the grid; there is no default to fall back on.
Clear enough to supply this argument.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data.
{
"name": "cupid-present-mortal",
"title": "Meet the Mortal",
"description": "Present the fictional mortal character for the Cupid matchmaking game. Shows their zodiac-based personality. The player picks a mortal in the Home chooser ('I choose {Name} as my mortal') — pass `mortal=\"{Name}\"` (the exact name). Never call it in the same turn as cupid-start-game: the chooser is on screen and the player hasn't picked yet. The tool echoes a `mortal_id` — thread it through the rest of the arc. After presenting, WAIT for user to say they're ready to meet the match. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"mortal": {
"type": "string",
"description": "The chosen mortal's name (e.g. from 'I choose {Name} as my mortal.'). The server resolves the name to its character id. Always pass it — the player picks from the grid; there is no default to fall back on."
},
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"mortal",
"mortal_id",
"game_date"
],
"properties": {
"mortal": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"game_date": {
"type": "string"
},
"mortal_id": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
Present THREE potential matches as a carousel of cards. User must SELECT one match before proceeding. Pass the `mortal_id` echoed by cupid-present-mortal so this loads the chosen mortal's matches. The widget will send a message like 'I choose [Name] as my match! (match_id=N, mortal_id=…)' when user selects — pass that name as match_name and that number as match_id to cupid-show-compatibility. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face.
Describe the returned information so the agent knows whether it will answer the request.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call.
{
"name": "cupid-present-matches",
"title": "Choose Your Match",
"description": "Present THREE potential matches as a carousel of cards. User must SELECT one match before proceeding. Pass the `mortal_id` echoed by cupid-present-mortal so this loads the chosen mortal's matches. The widget will send a message like 'I choose [Name] as my match! (match_id=N, mortal_id=…)' when user selects — pass that name as match_name and that number as match_id to cupid-show-compatibility. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"matches",
"mortal_id"
],
"properties": {
"matches": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
"mortal_id": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description75/100
Show compatibility analysis for the selected match. Pass match_name (the name in the player's 'I choose [Name] as my match!' message) AND match_id (the message carries it as `match_id=N`; otherwise the carousel position — 1=first, 2=second, 3=third). The server resolves the name; it wins over a disagreeing number. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face.
Describe the returned information so the agent knows whether it will answer the request.
Inputs95/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_id
ID of the selected match (1, 2, or 3). The card's message carries it as `match_id=N`; otherwise the position in the carousel — 1 is leftmost, 2 is middle, 3 is rightmost. Pass match_name as well.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_name
The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both.
Clear enough to supply this argument.
sun_narrative
SUN narrative for the widget's tap-to-open bottom sheet (identity & worldview). 2-3 sentences in Cupid's voice — dry, warm, precise. Read both signs: how each sees the world and whether their core identities clash or click. Reference the actual signs. No headers, no name labels (the widget shows those) — just the prose.
Clear enough to supply this argument.
moon_narrative
MOON narrative for the bottom sheet (emotional needs). 2-3 sentences in Cupid's voice. How each processes feelings and whether emotional safety is achievable or aspirational between these signs. Just the prose — no headers or labels.
Clear enough to supply this argument.
venus_narrative
VENUS narrative for the bottom sheet (love style). 2-3 sentences in Cupid's voice. What each wants from romance and whether they speak the same love language or order from different menus. Just the prose — no headers or labels.
Clear enough to supply this argument.
mars_narrative
MARS narrative for the bottom sheet (passion & conflict). 2-3 sentences in Cupid's voice. How each pursues desire and handles conflict — chemistry or combustion. Just the prose — no headers or labels.
Clear enough to supply this argument.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call.
{
"name": "cupid-show-compatibility",
"title": "Compatibility Analysis",
"description": "Show compatibility analysis for the selected match. Pass match_name (the name in the player's 'I choose [Name] as my match!' message) AND match_id (the message carries it as `match_id=N`; otherwise the carousel position — 1=first, 2=second, 3=third). The server resolves the name; it wins over a disagreeing number. Cupid serves its own fictional characters: their profiles and their portraits come from this app, and the card on screen already shows each portrait. They are not real people, so there is nothing to look up — never search the web, generate an image or show a photo for any of them; a found photo would be a real stranger's face.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"match_id"
],
"properties": {
"match_id": {
"enum": [
"1",
"2",
"3"
],
"type": "string",
"description": "ID of the selected match (1, 2, or 3). The card's message carries it as `match_id=N`; otherwise the position in the carousel — 1 is leftmost, 2 is middle, 3 is rightmost. Pass match_name as well."
},
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call."
},
"match_name": {
"type": "string",
"description": "The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both."
},
"sun_narrative": {
"type": "string",
"description": "SUN narrative for the widget's tap-to-open bottom sheet (identity & worldview). 2-3 sentences in Cupid's voice — dry, warm, precise. Read both signs: how each sees the world and whether their core identities clash or click. Reference the actual signs. No headers, no name labels (the widget shows those) — just the prose."
},
"mars_narrative": {
"type": "string",
"description": "MARS narrative for the bottom sheet (passion & conflict). 2-3 sentences in Cupid's voice. How each pursues desire and handles conflict — chemistry or combustion. Just the prose — no headers or labels."
},
"moon_narrative": {
"type": "string",
"description": "MOON narrative for the bottom sheet (emotional needs). 2-3 sentences in Cupid's voice. How each processes feelings and whether emotional safety is achievable or aspirational between these signs. Just the prose — no headers or labels."
},
"venus_narrative": {
"type": "string",
"description": "VENUS narrative for the bottom sheet (love style). 2-3 sentences in Cupid's voice. What each wants from romance and whether they speak the same love language or order from different menus. Just the prose — no headers or labels."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"mortal",
"match",
"compatibility"
],
"properties": {
"match": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"mortal": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"compatibility": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description60/100
Show final evaluation and Cupid's revealed astrological tendencies.
Describe the returned information so the agent knows whether it will answer the request.
Inputs93/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_id
ID of the selected match (1, 2, or 3)
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_name
The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both.
Clear enough to supply this argument.
final_score
Final score after Cupid's influence (0-100)
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
cupid_sign
Cupid's dominant zodiac sign revealed through choices (e.g., 'Libra', 'Scorpio')
Clear enough to supply this argument.
cupid_sign_label
A short, evocative tagline for this Cupid sign (e.g., 'First through every time' for Aries)
Clear enough to supply this argument.
title
A romantic comedy title for this date — specific to the location or vibe, not generic (e.g., 'A Valentine's Eve in the Seaport')
Clear enough to supply this argument.
tagline
One italic line under the title — the date's subtitle (e.g., 'Two fire signs, one gallery, zero chaperones.')
Clear enough to supply this argument.
story
STORY tab: a 4-5 line storybook recounting of THIS date, past tense, house voice. Rendered with a drop cap — open with a strong sentence, plain prose, no markup.
Clear enough to supply this argument.
choices › items › scene
The scene's name (e.g., 'The Meet-Cute')
Clear enough to supply this argument.
choices › items › label
The choice Cupid made in that scene
Clear enough to supply this argument.
choices › items › descriptor
One italic clause of what the choice did
Clear enough to supply this argument.
behavior_summary
A two-clause characterization of how Cupid played this date, in the house voice. Exactly two clauses, no astrological tags (e.g., 'Bold at the door, patient at the table — you pushed only when the stars pushed back.')
Clear enough to supply this argument.
date_number
Which date this scorecard closes. Omit on the first date; dates 2+ (opened by cupid-dates) must pass it.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
initial_score
Dates 2+ only: the score carried into this date — the previous scorecard's final score. REQUIRED when date_number >= 2. Ignored on date 1, where the server reads the compatibility score.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
moment › quote
The line, quoted exactly as spoken (≤ ~120 chars).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
moment › said_by
A first name — matched to mortal/match for display only.
Clear enough to supply this argument.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call.
{
"name": "cupid-complete-game",
"title": "Cupid's Evaluation",
"description": "Show final evaluation and Cupid's revealed astrological tendencies.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"match_id",
"final_score",
"cupid_sign",
"cupid_sign_label",
"title",
"behavior_summary"
],
"properties": {
"story": {
"type": "string",
"description": "STORY tab: a 4-5 line storybook recounting of THIS date, past tense, house voice. Rendered with a drop cap — open with a strong sentence, plain prose, no markup."
},
"title": {
"type": "string",
"description": "A romantic comedy title for this date — specific to the location or vibe, not generic (e.g., 'A Valentine's Eve in the Seaport')"
},
"moment": {
"type": "object",
"required": [
"quote",
"said_by"
],
"properties": {
"quote": {
"type": "string",
"description": "The line, quoted exactly as spoken (≤ ~120 chars)."
},
"said_by": {
"type": "string",
"description": "A first name — matched to mortal/match for display only."
}
},
"description": "ONE line from tonight a person would repeat tomorrow. Pass it on the next cupid-dates call — it travels with the record (the card no longer prints it). Write it now, while the dialogue is still in front of you."
},
"choices": {
"type": "array",
"items": {
"type": "object",
"required": [
"scene",
"label",
"descriptor"
],
"properties": {
"label": {
"type": "string",
"description": "The choice Cupid made in that scene"
},
"scene": {
"type": "string",
"description": "The scene's name (e.g., 'The Meet-Cute')"
},
"descriptor": {
"type": "string",
"description": "One italic clause of what the choice did"
}
}
},
"description": "CHOICES tab: exactly FOUR entries, one per scene of this date, in order. Every date has four scenes."
},
"tagline": {
"type": "string",
"description": "One italic line under the title — the date's subtitle (e.g., 'Two fire signs, one gallery, zero chaperones.')"
},
"match_id": {
"type": "integer",
"maximum": 3,
"minimum": 1,
"description": "ID of the selected match (1, 2, or 3)"
},
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call."
},
"cupid_sign": {
"type": "string",
"description": "Cupid's dominant zodiac sign revealed through choices (e.g., 'Libra', 'Scorpio')"
},
"match_name": {
"type": "string",
"description": "The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both."
},
"date_number": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "Which date this scorecard closes. Omit on the first date; dates 2+ (opened by cupid-dates) must pass it."
},
"final_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Final score after Cupid's influence (0-100)"
},
"initial_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Dates 2+ only: the score carried into this date — the previous scorecard's final score. REQUIRED when date_number >= 2. Ignored on date 1, where the server reads the compatibility score."
},
"behavior_summary": {
"type": "string",
"description": "A two-clause characterization of how Cupid played this date, in the house voice. Exactly two clauses, no astrological tags (e.g., 'Bold at the door, patient at the table — you pushed only when the stars pushed back.')"
},
"cupid_sign_label": {
"type": "string",
"description": "A short, evocative tagline for this Cupid sign (e.g., 'First through every time' for Aries)"
}
}
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"mortal_id",
"next",
"initial_score",
"final_score",
"cupid_sign",
"cupid_sign_label",
"title",
"tagline",
"story",
"choices",
"behavior_summary",
"date_number",
"impact",
"cupid_sign_image",
"mortal_name",
"mortal_image",
"mortal_sign",
"mortal_occupation",
"match_name",
"match_image",
"match_sign",
"match_occupation",
"game_date",
"match_id"
],
"properties": {
"next": {
"type": "string"
},
"story": {
"type": "string"
},
"title": {
"type": "string"
},
"impact": {
"type": "number"
},
"choices": {
"type": "array",
"items": {
"type": "object",
"required": [
"scene",
"label",
"descriptor"
],
"properties": {
"label": {
"type": "string"
},
"scene": {
"type": "string"
},
"descriptor": {
"type": "string"
}
},
"additionalProperties": false
}
},
"tagline": {
"type": "string"
},
"match_id": {
"type": "number"
},
"game_date": {
"type": "string"
},
"mortal_id": {
"type": "string"
},
"cupid_sign": {
"type": "string"
},
"match_name": {
"type": "string"
},
"match_sign": {
"type": "string"
},
"date_number": {
"type": "number"
},
"final_score": {
"type": "number"
},
"match_image": {
"type": "string"
},
"mortal_name": {
"type": "string"
},
"mortal_sign": {
"type": "string"
},
"mortal_image": {
"type": "string"
},
"initial_score": {
"type": "number"
},
"behavior_summary": {
"type": "string"
},
"cupid_sign_image": {
"type": "string"
},
"cupid_sign_label": {
"type": "string"
},
"match_occupation": {
"type": "string"
},
"mortal_occupation": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description77/100
Open date N (2, 3, 4, …) for the current couple after the player takes the Dates door. Renders the date chapter card and returns the continuing-date playbook.
Describe the returned information so the agent knows whether it will answer the request.
Inputs82/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_id
ID of the matched partner (1, 2, or 3) — the same match the couple has been dating
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_name
The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both.
Clear enough to supply this argument.
date_number
Which date this opens (2, 3, 4, …). The first date never goes through this tool.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
initial_score
The score carried into this date — the previous scorecard's final score.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
previous_title
The previous date's rom-com title (e.g. 'A Night in Williamsburg') — it travels with the record; the one-page chapter card no longer prints a 'Previously' line.
Clear enough to supply this argument.
story_so_far
ONE sentence in Cupid's voice (≤ ~140 characters) on where the couple stands going into this date — shown as the italic 'story so far' line on the date card.
Clear enough to supply this argument.
previous_impact
The previous date's impact (its final_score minus its initial_score), passed through from the scorecard. Kept for the record; the card only reads it when `dates` is missing, to seed the rail.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
moment › quote
≤ ~120 chars; the handler clamps at 160.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
moment › said_by
A first name — matched to mortal/match for display only.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
opening › question
Fixed for now: 'Where should they meet?'
Clear enough to supply this argument.
opening › choices › items › name
Short scene name for the card's pill — 2-3 words, e.g. 'The Rooftop'.
Clear enough to supply this argument.
opening › choices › items › title
≤ ~32 chars — a specific place these two would pick.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
opening › choices › items › tease
≤ ~60 chars — the merit, result, or consequence of choosing it.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
dates › items › n
The date's number (1 = the first date).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
dates › items › from
Its initial score — the score going in.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
dates › items › to
Its final score, from the scorecard.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"name": "cupid-dates",
"title": "The Next Date",
"description": "Open date N (2, 3, 4, …) for the current couple after the player takes the Dates door. Renders the date chapter card and returns the continuing-date playbook.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"match_id",
"date_number",
"initial_score"
],
"properties": {
"dates": {
"type": "array",
"items": {
"type": "object",
"required": [
"n",
"from",
"to"
],
"properties": {
"n": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "The date's number (1 = the first date)."
},
"to": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its final score, from the scorecard."
},
"from": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its initial score — the score going in."
}
}
},
"description": "Every date played so far — one {n, from, to} per scorecard you issued, the same array cupid-fates takes. The card draws the story's rail from it (a circle per date, coloured by its score); without it the rail is drawn from the carried score alone."
},
"moment": {
"type": "object",
"required": [
"quote",
"said_by"
],
"properties": {
"quote": {
"type": "string",
"description": "≤ ~120 chars; the handler clamps at 160."
},
"said_by": {
"type": "string",
"description": "A first name — matched to mortal/match for display only."
}
},
"description": "ONE line from the previous date, quoted exactly as spoken; the line a person would repeat to a friend the next day."
},
"opening": {
"type": "object",
"required": [
"question",
"choices"
],
"properties": {
"choices": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"name": {
"type": "string",
"description": "Short scene name for the card's pill — 2-3 words, e.g. 'The Rooftop'."
},
"tease": {
"type": "string",
"description": "≤ ~60 chars — the merit, result, or consequence of choosing it."
},
"title": {
"type": "string",
"description": "≤ ~32 chars — a specific place these two would pick."
}
}
},
"maxItems": 2,
"minItems": 2,
"description": "Exactly two openings — the card draws two, side by side on desktop."
},
"question": {
"type": "string",
"description": "Fixed for now: 'Where should they meet?'"
}
},
"description": "REQUIRED. Two (or three) ways this date could open — you write them; they are not on file. The card draws only what you send, and a call without them is refused. The player's pick is Scene 1's premise."
},
"match_id": {
"type": "integer",
"maximum": 3,
"minimum": 1,
"description": "ID of the matched partner (1, 2, or 3) — the same match the couple has been dating"
},
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call."
},
"match_name": {
"type": "string",
"description": "The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both."
},
"date_number": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 2,
"description": "Which date this opens (2, 3, 4, …). The first date never goes through this tool."
},
"story_so_far": {
"type": "string",
"description": "ONE sentence in Cupid's voice (≤ ~140 characters) on where the couple stands going into this date — shown as the italic 'story so far' line on the date card."
},
"initial_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "The score carried into this date — the previous scorecard's final score."
},
"previous_title": {
"type": "string",
"description": "The previous date's rom-com title (e.g. 'A Night in Williamsburg') — it travels with the record; the one-page chapter card no longer prints a 'Previously' line."
},
"previous_impact": {
"type": "integer",
"maximum": 100,
"minimum": -100,
"description": "The previous date's impact (its final_score minus its initial_score), passed through from the scorecard. Kept for the record; the card only reads it when `dates` is missing, to seed the rail."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"date_number",
"initial_score",
"previous_title",
"next",
"mortal_name",
"mortal_image",
"mortal_sign",
"match_name",
"match_image",
"match_sign",
"game_date",
"match_id"
],
"properties": {
"next": {
"type": "string"
},
"dates": {
"type": "array",
"items": {
"type": "object",
"required": [
"n",
"from",
"to"
],
"properties": {
"n": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "The date's number (1 = the first date)."
},
"to": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its final score, from the scorecard."
},
"from": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its initial score — the score going in."
}
},
"additionalProperties": false
}
},
"moment": {
"type": "object",
"required": [
"quote",
"said_by"
],
"properties": {
"quote": {
"type": "string"
},
"said_by": {
"type": "string"
}
},
"additionalProperties": false
},
"opening": {
"type": "object",
"required": [
"question",
"choices"
],
"properties": {
"choices": {
"type": "array",
"items": {
"type": "object",
"required": [
"title"
],
"properties": {
"name": {
"type": "string"
},
"tease": {
"type": "string"
},
"title": {
"type": "string"
}
},
"additionalProperties": false
}
},
"question": {
"type": "string"
}
},
"additionalProperties": false
},
"match_id": {
"type": "number"
},
"game_date": {
"type": "string"
},
"match_name": {
"type": "string"
},
"match_sign": {
"type": "string"
},
"date_number": {
"type": "number"
},
"match_image": {
"type": "string"
},
"mortal_name": {
"type": "string"
},
"mortal_sign": {
"type": "string"
},
"mortal_image": {
"type": "string"
},
"story_so_far": {
"type": "string"
},
"initial_score": {
"type": "number"
},
"previous_title": {
"type": "string"
},
"previous_impact": {
"type": "number"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description66/100
Draw the Fates card at the crossroads — the couple's potential and the story's rail — after the player takes the Fates door. The ending is not told here: when the player's message is "Leave it to the Fates." call cupid-fates-reveal.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_id
ID of the matched partner (1, 2, or 3) — the couple at the crossroads
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_name
The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both.
Clear enough to supply this argument.
final_score
The final score from the scorecard just shown — it alone sets the band the couple's rung sits on.
Clear enough to supply this argument.
cupid_says
The send-off: ONE or TWO sentences in the narrator's voice, ≤ ~200 chars — the laying down of the bow, e.g. 'You step out, Cupid, and let the Fates take their course.' Do NOT name the band or its word on the scale, and do NOT say whether they end up together — the card's labeled scale carries the ranking. Never contradict the band.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
dates › items › n
The date's number (1 = the first date).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
dates › items › from
Its initial score — the score going in.
Clear enough to supply this argument.
dates › items › to
Its final score, from the scorecard.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call.
{
"name": "cupid-fates",
"title": "The Fates",
"description": "Draw the Fates card at the crossroads — the couple's potential and the story's rail — after the player takes the Fates door. The ending is not told here: when the player's message is \"Leave it to the Fates.\" call cupid-fates-reveal.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"match_id",
"final_score"
],
"properties": {
"dates": {
"type": "array",
"items": {
"type": "object",
"required": [
"n",
"from",
"to"
],
"properties": {
"n": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "The date's number (1 = the first date)."
},
"to": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its final score, from the scorecard."
},
"from": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its initial score — the score going in."
}
}
},
"description": "Every date played — {n, from, to} from the scorecards you issued. The card draws the story's rail from it."
},
"match_id": {
"type": "integer",
"maximum": 3,
"minimum": 1,
"description": "ID of the matched partner (1, 2, or 3) — the couple at the crossroads"
},
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call."
},
"cupid_says": {
"type": "string",
"description": "The send-off: ONE or TWO sentences in the narrator's voice, ≤ ~200 chars — the laying down of the bow, e.g. 'You step out, Cupid, and let the Fates take their course.' Do NOT name the band or its word on the scale, and do NOT say whether they end up together — the card's labeled scale carries the ranking. Never contradict the band."
},
"match_name": {
"type": "string",
"description": "The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both."
},
"final_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "The final score from the scorecard just shown — it alone sets the band the couple's rung sits on."
}
}
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"pair",
"mortal_id",
"mortal_image",
"mortal_sign",
"match_image",
"match_sign",
"score",
"band",
"next_up",
"cupid_says",
"game_date",
"match_id",
"next"
],
"properties": {
"band": {
"type": "object",
"required": [
"range"
],
"properties": {
"range": {
"type": "string"
}
},
"additionalProperties": false
},
"next": {
"type": "string"
},
"pair": {
"type": "array",
"items": {
"type": "string"
}
},
"dates": {
"type": "array",
"items": {
"type": "object",
"required": [
"n",
"from",
"to"
],
"properties": {
"n": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "The date's number (1 = the first date)."
},
"to": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its final score, from the scorecard."
},
"from": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Its initial score — the score going in."
}
},
"additionalProperties": false
}
},
"score": {
"type": "number"
},
"next_up": {
"anyOf": [
{
"type": "object",
"required": [
"points"
],
"properties": {
"points": {
"type": "number"
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"match_id": {
"type": "number"
},
"game_date": {
"type": "string"
},
"mortal_id": {
"type": "string"
},
"cupid_says": {
"type": "string"
},
"match_sign": {
"type": "string"
},
"match_image": {
"type": "string"
},
"mortal_sign": {
"type": "string"
},
"mortal_image": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
Align the title with the capability actually described by this tool.
Description93/100
The ending the couple's score has earned. Call it only after the Fates card is on screen and the player's message is "Leave it to the Fates." — never straight from the scorecard — with the same mortal_id, match_id and final_score the Fates card was drawn with. Returns the band, whether they end up together, the whole forecast and the epilogue playbook — then write the epilogue as your reply. No tool follows.
The description explains the capability, when to use it, and what to expect.
Inputs94/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_id
ID of the matched partner (1, 2, or 3) — the couple at the crossroads
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
match_name
The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both.
Clear enough to supply this argument.
final_score
The final score from the scorecard just shown — it alone sets the band the couple's rung sits on.
Clear enough to supply this argument.
mortal_id
The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call.
{
"name": "cupid-fates-reveal",
"title": "The Fates have spoken",
"description": "The ending the couple's score has earned. Call it only after the Fates card is on screen and the player's message is \"Leave it to the Fates.\" — never straight from the scorecard — with the same mortal_id, match_id and final_score the Fates card was drawn with. Returns the band, whether they end up together, the whole forecast and the epilogue playbook — then write the epilogue as your reply. No tool follows.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"match_id",
"final_score"
],
"properties": {
"match_id": {
"type": "integer",
"maximum": 3,
"minimum": 1,
"description": "ID of the matched partner (1, 2, or 3) — the couple at the crossroads"
},
"mortal_id": {
"type": "string",
"description": "The chosen character's id — `mortal_id` in cupid-present-mortal's result. If you don't have it, pass the mortal's exact name instead (e.g. 'Celeste O.'); the server resolves it. Never invent an id. Pass it so this tool loads the CHOSEN mortal's data. REQUIRED: without it this tool cannot know which mortal is in play and will refuse the call."
},
"match_name": {
"type": "string",
"description": "The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both."
},
"final_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "The final score from the scorecard just shown — it alone sets the band the couple's rung sits on."
}
}
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"pair",
"score",
"band",
"ladder",
"next_up",
"game_date",
"match_id",
"next"
],
"properties": {
"band": {
"type": "object",
"required": [
"key",
"range",
"name",
"line",
"together"
],
"properties": {
"key": {
"type": "string"
},
"line": {
"type": "string"
},
"name": {
"type": "string"
},
"range": {
"type": "string"
},
"together": {
"type": "boolean"
}
},
"additionalProperties": false
},
"next": {
"type": "string"
},
"pair": {
"type": "array",
"items": {
"type": "string"
}
},
"score": {
"type": "number"
},
"ladder": {
"type": "array",
"items": {
"type": "object",
"required": [
"key",
"range",
"name",
"together"
],
"properties": {
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"range": {
"type": "string"
},
"together": {
"type": "boolean"
}
},
"additionalProperties": false
}
},
"next_up": {
"anyOf": [
{
"type": "object",
"required": [
"points",
"name"
],
"properties": {
"name": {
"type": "string"
},
"points": {
"type": "number"
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"match_id": {
"type": "number"
},
"game_date": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
Name the specific action and subject instead of using a generic label such as ‘manage’ or ‘tool’.
Description69/100
Plays a scene. Draws the scene card — the chapter's title and narration, the dialogue as a script with the couple's faces, and Cupid's 3-4 choices on its last page — which the player pages through and presses. Put the whole scene in scene_title, narration and dialogue — the same scene you would have written — and pass mortal_id and match_id so the card knows the couple. On this host the card is always drawn above your words, so a scene written as text arrives after its own choices: never write the scene or the options as text; a short line of your own around the card is fine. After the fourth scene (or an early exit), call cupid-complete-game instead.
Describe the returned information so the agent knows whether it will answer the request.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
scene
Which scene this call closes, 1–4. Pass it every time — it sets the widget's click and the NEXT note in this result.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
prompt
Brief intro line shown above the options (e.g., "What's your move?")
Clear enough to supply this argument.
options › items › letter
Option letter — A, B, C, D in order, no gap
Clear enough to supply this argument.
options › items › title
Option title in caps (e.g., 'LET ESPERANZA LEAD')
Clear enough to supply this argument.
options › items › label
Strategic label (e.g., 'The Direct Approach')
Clear enough to supply this argument.
options › items › advice
Specific tactical guidance for the Mortal
Clear enough to supply this argument.
options › items › benefits
What could go right (1-2 items)
Clear enough to supply this argument.
options › items › risks
What could go wrong (1-2 items)
Clear enough to supply this argument.
date_number
Which date this scene belongs to — 1 for the first date, 2 for the second, as given by cupid-dates. The card's footer names it.
Clear enough to supply this argument.
mortal_id
The mortal's id, as echoed by cupid-present-mortal — the card draws the couple's faces from it.
Clear enough to supply this argument.
match_id
The chosen match (1, 2 or 3), as passed to cupid-show-compatibility — the other face on the card.
Clear enough to supply this argument.
match_name
The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both.
Clear enough to supply this argument.
scene_title
The scene's title, as you would head it — e.g. 'Scene 3: The Turning Point'
Clear enough to supply this argument.
narration
The scene's narration, 2-3 paragraphs, newlines kept — first the outcome of the previous choice, then the new scene's place and mood. Drawn in the card above the dialogue.
Clear enough to supply this argument.
dialogue › items › speaker
Who speaks, as you label them — 'ESPERANZA'
Clear enough to supply this argument.
dialogue › items › line
The line as spoken; a stage direction stays inside it, in parentheses
{
"name": "cupid-present-options",
"title": "The Scene",
"description": "Plays a scene. Draws the scene card — the chapter's title and narration, the dialogue as a script with the couple's faces, and Cupid's 3-4 choices on its last page — which the player pages through and presses. Put the whole scene in scene_title, narration and dialogue — the same scene you would have written — and pass mortal_id and match_id so the card knows the couple. On this host the card is always drawn above your words, so a scene written as text arrives after its own choices: never write the scene or the options as text; a short line of your own around the card is fine. After the fourth scene (or an early exit), call cupid-complete-game instead.",
"inputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"options"
],
"properties": {
"scene": {
"type": "number",
"description": "Which scene this call closes, 1–4. Pass it every time — it sets the widget's click and the NEXT note in this result."
},
"prompt": {
"type": "string",
"description": "Brief intro line shown above the options (e.g., \"What's your move?\")"
},
"options": {
"type": "array",
"items": {
"type": "object",
"required": [
"letter",
"title",
"label",
"advice",
"benefits",
"risks"
],
"properties": {
"label": {
"type": "string",
"description": "Strategic label (e.g., 'The Direct Approach')"
},
"risks": {
"type": "array",
"items": {
"type": "string"
},
"description": "What could go wrong (1-2 items)"
},
"title": {
"type": "string",
"description": "Option title in caps (e.g., 'LET ESPERANZA LEAD')"
},
"advice": {
"type": "string",
"description": "Specific tactical guidance for the Mortal"
},
"letter": {
"type": "string",
"description": "Option letter — A, B, C, D in order, no gap"
},
"benefits": {
"type": "array",
"items": {
"type": "string"
},
"description": "What could go right (1-2 items)"
}
}
},
"maxItems": 4,
"minItems": 3,
"description": "3-4 strategic options for the player to choose from, lettered A, B, C, D in order. A call whose letters have a gap (a dropped option) is refused and must be resent whole."
},
"dialogue": {
"type": "array",
"items": {
"type": "object",
"required": [
"speaker",
"line"
],
"properties": {
"line": {
"type": "string",
"description": "The line as spoken; a stage direction stays inside it, in parentheses"
},
"speaker": {
"type": "string",
"description": "Who speaks, as you label them — 'ESPERANZA'"
}
}
},
"description": "The scene's dialogue in order, 8-12 exchanges, each {speaker, line} — witty, character-revealing, building to the decision point and stopped before it resolves. Drawn in the card beneath the narration, above the cards."
},
"match_id": {
"type": "number",
"description": "The chosen match (1, 2 or 3), as passed to cupid-show-compatibility — the other face on the card."
},
"mortal_id": {
"type": "string",
"description": "The mortal's id, as echoed by cupid-present-mortal — the card draws the couple's faces from it."
},
"narration": {
"type": "string",
"description": "The scene's narration, 2-3 paragraphs, newlines kept — first the outcome of the previous choice, then the new scene's place and mood. Drawn in the card above the dialogue."
},
"match_name": {
"type": "string",
"description": "The chosen match's name exactly as the player's message gives it (e.g. 'Camilo V.' from 'I choose Camilo V. as my match!'). The server resolves it to the match_id, and it wins over a disagreeing match_id — always pass both."
},
"date_number": {
"type": "number",
"description": "Which date this scene belongs to — 1 for the first date, 2 for the second, as given by cupid-dates. The card's footer names it."
},
"scene_title": {
"type": "string",
"description": "The scene's title, as you would head it — e.g. 'Scene 3: The Turning Point'"
}
}
},
"outputSchema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"prompt",
"options",
"next"
],
"properties": {
"next": {
"type": "string"
},
"scene": {
"type": "number"
},
"couple": {
"type": "object",
"required": [
"mortal",
"match"
],
"properties": {
"match": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"image": {
"type": "string"
}
},
"additionalProperties": false
},
"mortal": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"image": {
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"prompt": {
"type": "string"
},
"options": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
"dialogue": {
"type": "array",
"items": {
"type": "object",
"required": [
"speaker",
"line"
],
"properties": {
"line": {
"type": "string"
},
"speaker": {
"type": "string"
}
},
"additionalProperties": false
}
},
"narration": {
"type": "string"
},
"date_number": {
"type": "number"
},
"scene_title": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}
}
Loading score analytics…
Put your MCP to the test
A few tasks worth trying with this server, chosen from its reviewed tools. These have not been run.
01Compatibility AnalysisShow compatibility analysis for the selected match.
02Choose Your MatchPresent THREE potential matches as a carousel of cards.
03Scene GuideLoad scene structure rules and playbook for running the 4 scenes
04Meet the MortalPresent the fictional mortal character for the Cupid matchmaking game.
05The Fates have spokenThe ending the couple's score has earned.
Want to run these tasks against your MCP server with us?
Cupid setup, tools, quality score, publishing readiness, and alternatives.
How do I add Cupid to Claude, ChatGPT, or Cursor?
Add Cupid to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://cupid-mcp.playfulscience.ai/mcp.
Is Cupid MCP ready for ChatGPT and Claude?
As of November 3, 2026, Cupid scores 95/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is Cupid's MCP tool documentation?
As of November 3, 2026, Cupid scores 81/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 10 of 10 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
How can Cupid improve its MCP documentation?
cupid-present-options is the lowest-scoring reviewed tool at 69/100. Name the specific action and subject instead of using a generic label such as ‘manage’ or ‘tool’. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.