Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/.upstream-base
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2776ddd2355d6d6c8747d3964600f28daf62f049
6b0300214a09fd6029cfb7077043125758cd1fd2
5 changes: 5 additions & 0 deletions .cursor-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,11 @@
"name": "tesla",
"source": "third_party/tesla",
"description": "Read your Tesla cars and energy sites, and send commands you confirm."
},
{
"name": "fitmetrics",
"source": "third_party/fitmetrics",
"description": "Review Trainerize clients and check-ins, and update macros, messages, and programs."
}
]
}
49 changes: 49 additions & 0 deletions third_party/fitmetrics/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "fitmetrics",
"displayName": "FitMetrics",
"version": "1.0.0",
"minClientVersions": {
"cursor": "3.13.0"
},
"description": "Review Trainerize clients and check-ins, and update macros, messages, and programs.",
"author": {
"name": "Cursor",
"email": "plugins@cursor.com"
},
"homepage": "https://app.fitmetrics.ai/docs/faq/connect-ai-tools-to-fitmetrics-via-mcp-claude-chatgpt-openclaw-more",
"repository": "https://github.com/cursor/plugins",
"license": "MIT",
"logo": "assets/logo.svg",
"keywords": [
"fitmetrics",
"trainerize",
"abc fitness",
"coaching",
"fitness",
"nutrition",
"workouts",
"check-ins",
"mcp"
],
"category": "integrations",
"tags": [
"fitmetrics",
"fitness",
"coaching",
"mcp"
],
"variables": {
"type": "object",
"properties": {
"FITMETRICS_API_KEY": {
"type": "string",
"title": "FitMetrics API key",
"description": "Key from FitMetrics Settings → Integrations → MCP → Create API Key → Other MCP app. Requires the Scale package."
}
},
"required": [
"FITMETRICS_API_KEY"
]
},
"mcpServers": "./mcp.json"
}
9 changes: 9 additions & 0 deletions third_party/fitmetrics/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

All notable changes to this plugin will be documented here.

## 1.0.0 — initial release

- Added the `fitmetrics` MCP server pointing at FitMetrics' hosted Streamable HTTP endpoint (`https://app.fitmetrics.ai/mcp`).
- Auth uses a FitMetrics API key supplied by the user as an `Authorization: Bearer` header (`${FITMETRICS_API_KEY}`).
- Logo: FitMetrics' official mark, the `favicon.svg` from fitmetrics.ai.
21 changes: 21 additions & 0 deletions third_party/fitmetrics/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Cursor

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
65 changes: 65 additions & 0 deletions third_party/fitmetrics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# FitMetrics

Cursor plugin that connects agents to [FitMetrics](https://www.fitmetrics.ai) through FitMetrics' official remote [Model Context Protocol](https://modelcontextprotocol.io/) server.

Review your ABC Trainerize clients, check-ins, measurements, meals, and workouts, and update macros, messages, habits, and workout programs. FitMetrics is ABC Fitness's coaching add-on for Trainerize.

## Install

1. Open **Cursor Settings → Plugins**.
2. Search for **FitMetrics**.
3. Click **Install**, then set your FitMetrics API key (below).

Or run `/add-plugin fitmetrics` in chat.

## MCP

```json
{
"mcpServers": {
"fitmetrics": {
"type": "http",
"url": "https://app.fitmetrics.ai/mcp",
"headers": {
"Authorization": "Bearer ${FITMETRICS_API_KEY}"
}
}
}
}
```

Auth is a FitMetrics **API key** sent as `Authorization: Bearer`. In FitMetrics, open **Settings → Integrations → MCP**, click **Create API Key**, choose **Other MCP app**, then name the key and pick its coach and tool permissions. Set the key in **Dashboard → Plugins → Configure**. Do not commit the key.

## Before you connect

You need ABC Trainerize with the FitMetrics **Scale** package, the only package with MCP access. Coaches can create their own key, and it reaches only their assigned clients. Write actions stay off until an owner or admin turns them on.

## What agents can do

| Category | Capabilities |
| --- | --- |
| Clients | Morning briefing, client dossiers, measurements, habits, and tags |
| Check-ins | Review check-ins, and create and manage AI check-in templates and AI Forms |
| Nutrition | Meals and macros, including scheduled macro changes in Trainerize |
| Training | Workouts, cardio, 1:1 bookings, and building, copying, scheduling, and assigning programs |
| Messaging | Messages, scheduled and bulk messages, email, comments, and reactions |
| Automations | Create and manage FitMetrics automations |

FitMetrics lists 359 tools (137 read, 222 write). The hosted runtime is the source of truth for tool names and schemas.

## Notes

- FitMetrics offers OAuth sign-in only to Claude and ChatGPT, and its dynamic client registration rejects Cursor's OAuth callback. This plugin uses the API key path FitMetrics documents for Cursor and other MCP apps.
- Changes made through the server are confirmed, scoped, and logged in FitMetrics.

## Docs

- Connect AI tools to FitMetrics via MCP: https://app.fitmetrics.ai/docs/faq/connect-ai-tools-to-fitmetrics-via-mcp-claude-chatgpt-openclaw-more
- ABC Trainerize x FitMetrics MCP: https://resources.trainerize.com/mcp
- Server URL: https://app.fitmetrics.ai/mcp

Logo is FitMetrics' official mark, the `favicon.svg` from fitmetrics.ai.

## License

MIT
1 change: 1 addition & 0 deletions third_party/fitmetrics/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions third_party/fitmetrics/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mcpServers": {
"fitmetrics": {
"type": "http",
"url": "https://app.fitmetrics.ai/mcp",
"headers": {
"Authorization": "Bearer ${FITMETRICS_API_KEY}"
}
}
}
}
2 changes: 1 addition & 1 deletion third_party/x/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "x",
"displayName": "X",
"version": "2.11.0",
"version": "2.11.1",
"minClientVersions": {
"cursor": "3.13.0"
},
Expand Down
5 changes: 5 additions & 0 deletions third_party/x/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this plugin will be documented here.

## 2.11.1 — Find a contact's chat, X DMs only via send_chat_message

- A new "Find or message a contact" section in the guide: find someone's thread with `get_chat_conversations` `participant_query` (their @username, `type` `direct`, `expansions` `participant_ids` to confirm it's them), keep paging while `has_more` is true, and retry with their @username, instead of scanning the inbox or looking the person up first.
- X DMs go out only through `send_chat_message`, never an email or Slack draft tool. When the host holds a send for approval, as Grok Bot's X Chat draft card does, the send repeats it with exactly the same arguments, without re-encrypting.

## 2.11.0 — Posting

- Requested `tweet.write` so agents can publish posts and replies with `create_posts` on `https://api.x.com/mcp`.
Expand Down
18 changes: 15 additions & 3 deletions third_party/x/skills/x-api-mcp-guide/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Once per session:

| Tool | Use |
| --- | --- |
| `get_chat_conversations` | The inbox, `max_results` 1000 |
| `get_chat_conversations` | The inbox, `max_results` 1000. `participant_query` finds one person's thread ([Find or message a contact](#find-or-message-a-contact)) |
| `get_chat_conversation` | One thread, including `participant_ids` / `member_ids` |
| `get_chat_conversation_events` | `data[].encoded_event` plus `meta.conversation_key_events`, newest first, `max_results` 100 |
| `get_users_public_keys` | Signing keys for senders, all versions, up to 100 `ids` per call |
Expand All @@ -163,6 +163,16 @@ For any set of events:

Each message's `status` is `verified`, `unencrypted`, or `unverified` (an unverified message still has its text). Focus on the content. Don't comment on encryption unprompted or call plain messages odd. Answer plainly from `status` when asked about security, and mention `unverified` briefly before acting on that message.

### Find or message a contact

To find the thread with someone the owner already chats with, or to message them:

1. `get_chat_conversations` with `participant_query` set to their @username (or a word of their name if you don't know it), `type` `direct`, `max_results` 1000, and `expansions` `participant_ids`. Don't list the whole inbox, and don't look the person up to get their id first.
2. Confirm it's them from the expanded participant's `username` and `name`. The match's `id` is the conversation id the other Chat tools take.
3. A page can be empty while `meta.has_more` is true: keep paging with `meta.next_token` and the same query until a match or `has_more` is false.
4. No match: retry with their @username if you searched by name, then check message requests by `sender_id`. Still nothing means they have no thread with the owner yet.
5. To message them, follow [Send or reply](#send-or-reply) with that `id`.

### Unread

For "what's unread" or "anything new", don't scan every conversation.
Expand All @@ -175,7 +185,7 @@ For "what's unread" or "anything new", don't scan every conversation.

### Read or summarize

Read every inbox conversation, not only the ones that look relevant: list with `get_chat_conversations` (`max_results` 1000, all pages), then decrypt each. Skip message requests unless asked; if `meta.has_message_requests` is true, end with one line offering them. To find a named person's thread, resolve their handle to an id and match participants, then fall back to message requests by `sender_id`. Never claim you checked everything unless you read every thread (and both request inboxes, if asked) to the end; otherwise say how many you read. Optionally `mark_chat_conversation_read` afterwards.
Read every inbox conversation, not only the ones that look relevant: list with `get_chat_conversations` (`max_results` 1000, all pages), then decrypt each. Skip message requests unless asked; if `meta.has_message_requests` is true, end with one line offering them. To find a named person's thread, see [Find or message a contact](#find-or-message-a-contact). Never claim you checked everything unless you read every thread (and both request inboxes, if asked) to the end; otherwise say how many you read. Optionally `mark_chat_conversation_read` afterwards.

### Message requests

Expand All @@ -187,7 +197,9 @@ Pending 1:1 requests aren't in `get_chat_conversations`. List, open, and accept

### Send or reply

The owner must approve the text unless they already told you to send or reply ("reply that I'll be there"). "Check my inbox" is not approval.
The owner must approve the text unless they already told you to send or reply ("reply that I'll be there"). "Check my inbox" is not approval. To message someone they already chat with, find the thread first ([Find or message a contact](#find-or-message-a-contact)).

X DMs go out only through `send_chat_message`; an email or Slack draft tool can't send them, so never route a DM there or tell the owner it needs one. If the host holds a `send_chat_message` call for the owner to approve (Grok Bot shows an X Chat draft card), call it again with exactly the same arguments, the same encrypted payload included (don't re-encrypt), once they press Send or tell you to send it.

- **Thread with a conversation key:** fetch events and `conversation_key_events`, `session-encrypt` with the approved text, then `send_chat_message` with `id`, `message_id`, `encoded_message_create_event`, and `encoded_message_event_signature`. Confirm without dumping ciphertext.
- **No conversation key yet** (first message, or only plain messages): get both users' public keys (`public_key` and `public_key_version`), `session-encrypt` with `prepare` set (same shape as `prepare-keys` input), call `add_conversation_keys` with its output **before** `send_chat_message`, and strip any `_local_*` fields. `add_conversation_keys` returning `UNAUTHORIZED_REQUESTING_USER` means you can't set keys there or the peer isn't on X Chat: stop and report.
Expand Down
Loading