{"openapi":"3.1.0","info":{"title":"Garasu MCP","version":"1.0.0","description":"Garasu AI learns from your past A/B tests to identify key patterns and recommend new tests based on evidence, not guessing. Call tools with JSON-RPC method tools/call on https://garasu.co/v1/mcp. Each tool name is a unique operation id.","contact":{"url":"https://garasu.co/contact"}},"servers":[{"url":"https://garasu.co"}],"paths":{"/v1/mcp":{"post":{"operationId":"garasuMcp","summary":"Garasu MCP, Streamable HTTP","description":"Model Context Protocol endpoint. Initialize a session, then call tools/list or tools/call. Tool arguments are typed per operation id in components.schemas.","security":[{"bearerAuth":[]},{"oauth2":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcToolsCall"}}}},"responses":{"200":{"description":"JSON-RPC result, or a text/event-stream body for Streamable HTTP."},"401":{"description":"Missing or rejected Bearer token, or OAuth challenge."}}}},"/.well-known/mcp.json":{"get":{"operationId":"getMcpServerCard","summary":"MCP server card","description":"Discovery document for the Garasu MCP server.","responses":{"200":{"description":"Server card.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"},"oauth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://garasu.co/oauth/authorize","tokenUrl":"https://garasu.co/oauth/token","scopes":{}}}}},"schemas":{"list_projects_arguments":{"type":"object","additionalProperties":false,"properties":{}},"get_project_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."}},"required":["project_id"]},"update_project_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"name":{"type":"string","description":"New name. 1–80 characters."},"url":{"type":"string","description":"New url, or an empty string to clear it. Max 255 characters."},"description":{"type":"string","description":"New description. Max 500 characters."}},"required":["project_id"]},"list_learnings_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"limit":{"type":"integer","description":"Page size. Default 50, max 50."},"cursor":{"type":"string","description":"Opaque cursor from the previous page's nextCursor. Omit for the first page."},"order_by":{"type":"string","description":"Sort field. strength_of_evidence (default), created_at, updated_at, or title."},"order":{"type":"string","description":"Sort direction. desc (default) or asc."}},"required":["project_id"]},"get_learning_arguments":{"type":"object","additionalProperties":false,"properties":{"learning_id":{"type":"string","format":"uuid","description":"Learning id from list_learnings or query_learnings."}},"required":["learning_id"]},"query_learnings_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"query":{"type":"string","description":"Natural-language search text. 1–2000 characters."},"limit":{"type":"integer","description":"Max learnings to return. Default 10, max 50."}},"required":["project_id","query"]},"import_experiment_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"experiment":{"type":"object","description":"The concluded experiment to store. Garasu computes processed_results.","additionalProperties":false,"properties":{"name":{"type":"string","description":"Display title. Max 200 characters. When omitted, Garasu uses the first 200 characters of the hypothesis."},"hypothesis":{"type":"string","description":"What was tested and why. 1–8000 characters."},"start_date":{"type":"string","description":"When the test started, as ISO 8601."},"end_date":{"type":"string","description":"When the test ended, as ISO 8601. Must be on or after start_date."},"variant_keys":{"type":"array","description":"Every arm, including the control. At least two unique keys.","items":{"type":"string"}},"control_variant_key":{"type":"string","description":"The control arm. Must be one of variant_keys."},"raw_results":{"type":"array","description":"One row per metric per variant. At least two. Each row needs metric, variant_key, users, and conversions or mean.","items":{"type":"object","additionalProperties":false,"properties":{"metric":{"type":"string","description":"Metric name. Max 120 characters."},"variant_key":{"type":"string","description":"Arm this row belongs to. Must be one of variant_keys."},"users":{"type":"integer","description":"Sample size. Must be greater than 0."},"conversions":{"type":"integer","description":"Conversion count for a rate metric. Cannot exceed users."},"mean":{"type":"number","description":"Observed mean for a continuous metric. Required when conversions is omitted."},"variance":{"type":"number","description":"Sample variance of the per-user metric. Preferred for mean metrics."},"sum_squares":{"type":"number","description":"Sum of squares of the per-user metric. Used when variance is omitted."}},"required":["metric","variant_key","users"]}},"metadata":{"type":"object","description":"Source details, such as source and source_id. Defaults to {}.","additionalProperties":true,"properties":{}},"conclusion":{"type":"string","description":"Outcome label, such as won, lost, or inconclusive. Max 40 characters."},"conclusion_summary":{"type":"string","description":"Short write-up of the outcome. Max 8000 characters."},"winning_variant":{"type":"string","description":"Winning arm, when the source named one. Max 80 characters."}},"required":["hypothesis","start_date","end_date","variant_keys","control_variant_key","raw_results"]}},"required":["project_id","experiment"]},"remove_experiment_arguments":{"type":"object","additionalProperties":false,"properties":{"experiment_id":{"type":"string","format":"uuid","description":"Experiment id returned by import_experiment."}},"required":["experiment_id"]},"list_experiments_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"limit":{"type":"integer","description":"Page size. Default 50, max 50."},"cursor":{"type":"string","description":"Opaque cursor from the previous page's nextCursor. Omit for the first page."},"order_by":{"type":"string","description":"Sort field. created_at (default), updated_at, start_date, end_date, or name."},"order":{"type":"string","description":"Sort direction. desc (default) or asc."}},"required":["project_id"]},"query_experiments_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"query":{"type":"string","description":"Natural-language search text. 1–2000 characters."},"limit":{"type":"integer","description":"Max experiments to return. Default 10, max 50."}},"required":["project_id","query"]},"is_dupe_experiment_arguments":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"experiment_spec":{"type":"object","description":"The proposed experiment. The embedding uses name and hypothesis. Jev also reads content when you send it.","additionalProperties":false,"properties":{"name":{"type":"string","description":"Display title. Max 200 characters. title is accepted as an alias."},"hypothesis":{"type":"string","description":"What the test would change and why. 1–8000 characters."},"content":{"type":"string","description":"Optional fuller spec, such as variants and the primary metric. Max 12000 characters."}},"required":["name","hypothesis"]}},"required":["project_id","experiment_spec"]},"get_experiment_arguments":{"type":"object","additionalProperties":false,"properties":{"experiment_id":{"type":"string","format":"uuid","description":"Experiment id from import_experiment, list_experiments, or query_experiments."}},"required":["experiment_id"]},"JsonRpcToolsCall":{"type":"object","required":["jsonrpc","method","params"],"properties":{"jsonrpc":{"const":"2.0"},"id":{"description":"Client-chosen request id."},"method":{"const":"tools/call"},"params":{"oneOf":[{"type":"object","title":"list_projects","description":"List the organization's projects.","required":["name","arguments"],"properties":{"name":{"const":"list_projects","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/list_projects_arguments"}},"additionalProperties":false},{"type":"object","title":"get_project","description":"Get a project by id, including experiment and learning counts and sync status.","required":["name","arguments"],"properties":{"name":{"const":"get_project","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/get_project_arguments"}},"additionalProperties":false},{"type":"object","title":"update_project","description":"Update a project's name, url, or description. Omit fields you do not want to change. Pass an empty url to clear it.","required":["name","arguments"],"properties":{"name":{"const":"update_project","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/update_project_arguments"}},"additionalProperties":false},{"type":"object","title":"list_learnings","description":"List a project's learnings, strongest evidence first by default. Each learning includes related_experiments plus last_synced_at and sync_status. Wait and list again while sync_status is syncing. Pass nextCursor to fetch the next page.","required":["name","arguments"],"properties":{"name":{"const":"list_learnings","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/list_learnings_arguments"}},"additionalProperties":false},{"type":"object","title":"get_learning","description":"Get a learning by id, including related experiment ids and the project's last_synced_at and sync_status.","required":["name","arguments"],"properties":{"name":{"const":"get_learning","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/get_learning_arguments"}},"additionalProperties":false},{"type":"object","title":"query_learnings","description":"Search a project's learnings by semantic similarity. Each learning includes related_experiments plus last_synced_at and sync_status. Wait and search again while sync_status is syncing.","required":["name","arguments"],"properties":{"name":{"const":"query_learnings","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/query_learnings_arguments"}},"additionalProperties":false},{"type":"object","title":"import_experiment","description":"Add a concluded experiment. Embeds the title and hypothesis, stores the experiment, and starts a learning extraction job. Do not send processed_results; Garasu computes them from raw_results.","required":["name","arguments"],"properties":{"name":{"const":"import_experiment","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/import_experiment_arguments"}},"additionalProperties":false},{"type":"object","title":"remove_experiment","description":"Undo one import_experiment. Deletes that experiment, its joins, and any learning left with no experiments. Cannot be undone.","required":["name","arguments"],"properties":{"name":{"const":"remove_experiment","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/remove_experiment_arguments"}},"additionalProperties":false},{"type":"object","title":"list_experiments","description":"List a project's experiments. Each row includes processed results, a headline, and related learnings. Pass nextCursor to fetch the next page.","required":["name","arguments"],"properties":{"name":{"const":"list_experiments","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/list_experiments_arguments"}},"additionalProperties":false},{"type":"object","title":"query_experiments","description":"Search a project's experiments by semantic similarity of the title and hypothesis. Returns the closest matches, not a full catalog.","required":["name","arguments"],"properties":{"name":{"const":"query_experiments","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/query_experiments_arguments"}},"additionalProperties":false},{"type":"object","title":"is_dupe_experiment","description":"Check whether a proposed experiment has already been run in this project. Embeds the name and hypothesis, then Jev scores the nearest stored experiments. Returns only those Jev scores above 0.9, most similar first.","required":["name","arguments"],"properties":{"name":{"const":"is_dupe_experiment","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/is_dupe_experiment_arguments"}},"additionalProperties":false},{"type":"object","title":"get_experiment","description":"Get an experiment by id.","required":["name","arguments"],"properties":{"name":{"const":"get_experiment","description":"Operation id."},"arguments":{"$ref":"#/components/schemas/get_experiment_arguments"}},"additionalProperties":false}]}},"additionalProperties":true}}},"x-mcp-tools":[{"name":"list_projects","description":"List the organization's projects. You need a project_id, or you want to see what already exists.","parameters":{"type":"object","additionalProperties":false,"properties":{}}},{"name":"get_project","description":"Get a project by id, including experiment and learning counts and sync status. You have a project id and need its details or counts.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."}},"required":["project_id"]}},{"name":"update_project","description":"Update a project's name, url, or description. Omit fields you do not want to change. Pass an empty url to clear it. The project exists and the user wants to rename it or change its url.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"name":{"type":"string","description":"New name. 1–80 characters."},"url":{"type":"string","description":"New url, or an empty string to clear it. Max 255 characters."},"description":{"type":"string","description":"New description. Max 500 characters."}},"required":["project_id"]}},{"name":"list_learnings","description":"List a project's learnings, strongest evidence first by default. Each learning includes related_experiments plus last_synced_at and sync_status. Wait and list again while sync_status is syncing. Pass nextCursor to fetch the next page. You need the learnings in a project, or the next page of that list.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"limit":{"type":"integer","description":"Page size. Default 50, max 50."},"cursor":{"type":"string","description":"Opaque cursor from the previous page's nextCursor. Omit for the first page."},"order_by":{"type":"string","description":"Sort field. strength_of_evidence (default), created_at, updated_at, or title."},"order":{"type":"string","description":"Sort direction. desc (default) or asc."}},"required":["project_id"]}},{"name":"get_learning","description":"Get a learning by id, including related experiment ids and the project's last_synced_at and sync_status. You have a learning_id and need its title, summary, evidence, related experiments, or sync status.","parameters":{"type":"object","additionalProperties":false,"properties":{"learning_id":{"type":"string","format":"uuid","description":"Learning id from list_learnings or query_learnings."}},"required":["learning_id"]}},{"name":"query_learnings","description":"Search a project's learnings by semantic similarity. Each learning includes related_experiments plus last_synced_at and sync_status. Wait and search again while sync_status is syncing. You need existing learnings related to a question, hypothesis, or idea in this project.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"query":{"type":"string","description":"Natural-language search text. 1–2000 characters."},"limit":{"type":"integer","description":"Max learnings to return. Default 10, max 50."}},"required":["project_id","query"]}},{"name":"import_experiment","description":"Add a concluded experiment. Embeds the title and hypothesis, stores the experiment, and starts a learning extraction job. Do not send processed_results; Garasu computes them from raw_results. You have a concluded test with results and want it stored on a project. Skip drafts and tests that are still running.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"experiment":{"type":"object","description":"The concluded experiment to store. Garasu computes processed_results.","additionalProperties":false,"properties":{"name":{"type":"string","description":"Display title. Max 200 characters. When omitted, Garasu uses the first 200 characters of the hypothesis."},"hypothesis":{"type":"string","description":"What was tested and why. 1–8000 characters."},"start_date":{"type":"string","description":"When the test started, as ISO 8601."},"end_date":{"type":"string","description":"When the test ended, as ISO 8601. Must be on or after start_date."},"variant_keys":{"type":"array","description":"Every arm, including the control. At least two unique keys.","items":{"type":"string"}},"control_variant_key":{"type":"string","description":"The control arm. Must be one of variant_keys."},"raw_results":{"type":"array","description":"One row per metric per variant. At least two. Each row needs metric, variant_key, users, and conversions or mean.","items":{"type":"object","additionalProperties":false,"properties":{"metric":{"type":"string","description":"Metric name. Max 120 characters."},"variant_key":{"type":"string","description":"Arm this row belongs to. Must be one of variant_keys."},"users":{"type":"integer","description":"Sample size. Must be greater than 0."},"conversions":{"type":"integer","description":"Conversion count for a rate metric. Cannot exceed users."},"mean":{"type":"number","description":"Observed mean for a continuous metric. Required when conversions is omitted."},"variance":{"type":"number","description":"Sample variance of the per-user metric. Preferred for mean metrics."},"sum_squares":{"type":"number","description":"Sum of squares of the per-user metric. Used when variance is omitted."}},"required":["metric","variant_key","users"]}},"metadata":{"type":"object","description":"Source details, such as source and source_id. Defaults to {}.","additionalProperties":true,"properties":{}},"conclusion":{"type":"string","description":"Outcome label, such as won, lost, or inconclusive. Max 40 characters."},"conclusion_summary":{"type":"string","description":"Short write-up of the outcome. Max 8000 characters."},"winning_variant":{"type":"string","description":"Winning arm, when the source named one. Max 80 characters."}},"required":["hypothesis","start_date","end_date","variant_keys","control_variant_key","raw_results"]}},"required":["project_id","experiment"]}},{"name":"remove_experiment","description":"Undo one import_experiment. Deletes that experiment, its joins, and any learning left with no experiments. Cannot be undone. An import_experiment call stored the wrong experiment and you need to remove it. Not for clearing a project.","parameters":{"type":"object","additionalProperties":false,"properties":{"experiment_id":{"type":"string","format":"uuid","description":"Experiment id returned by import_experiment."}},"required":["experiment_id"]}},{"name":"list_experiments","description":"List a project's experiments. Each row includes processed results, a headline, and related learnings. Pass nextCursor to fetch the next page. You need the experiments in a project, or the next page of that list.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"limit":{"type":"integer","description":"Page size. Default 50, max 50."},"cursor":{"type":"string","description":"Opaque cursor from the previous page's nextCursor. Omit for the first page."},"order_by":{"type":"string","description":"Sort field. created_at (default), updated_at, start_date, end_date, or name."},"order":{"type":"string","description":"Sort direction. desc (default) or asc."}},"required":["project_id"]}},{"name":"query_experiments","description":"Search a project's experiments by semantic similarity of the title and hypothesis. Returns the closest matches, not a full catalog. You need experiments in this project related to a question or hypothesis. This is a search, not a full catalog, and it has no cursor.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"query":{"type":"string","description":"Natural-language search text. 1–2000 characters."},"limit":{"type":"integer","description":"Max experiments to return. Default 10, max 50."}},"required":["project_id","query"]}},{"name":"is_dupe_experiment","description":"Check whether a proposed experiment has already been run in this project. Embeds the name and hypothesis, then Jev scores the nearest stored experiments. Returns only those Jev scores above 0.9, most similar first. You have a new experiment spec and need to know if this project already ran it. An empty list means it has not been run.","parameters":{"type":"object","additionalProperties":false,"properties":{"project_id":{"type":"string","format":"uuid","description":"Project id from list_projects."},"experiment_spec":{"type":"object","description":"The proposed experiment. The embedding uses name and hypothesis. Jev also reads content when you send it.","additionalProperties":false,"properties":{"name":{"type":"string","description":"Display title. Max 200 characters. title is accepted as an alias."},"hypothesis":{"type":"string","description":"What the test would change and why. 1–8000 characters."},"content":{"type":"string","description":"Optional fuller spec, such as variants and the primary metric. Max 12000 characters."}},"required":["name","hypothesis"]}},"required":["project_id","experiment_spec"]}},{"name":"get_experiment","description":"Get an experiment by id. You have an experiment_id and need the saved experiment, including raw results.","parameters":{"type":"object","additionalProperties":false,"properties":{"experiment_id":{"type":"string","format":"uuid","description":"Experiment id from import_experiment, list_experiments, or query_experiments."}},"required":["experiment_id"]}}]}