Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
23 changes: 23 additions & 0 deletions .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "kody",
"displayName": "Kody",
"version": "1.0.0",
"description": "Connect Cursor to your Kody personal assistant over remote MCP. Search capabilities, run sandboxed automations, manage secrets and packages, and keep memory and jobs that outlive the chat.",
"author": {
"name": "Kent C. Dodds",
"email": "me@kentcdodds.com"
},
"homepage": "https://heykody.dev",
"repository": "https://github.com/kentcdodds/kody",
"license": "MIT",
"keywords": [
"mcp",
"personal-assistant",
"automation",
"packages",
"secrets",
"remote-mcp"
],
"logo": "packages/worker/public/logo.png",
"mcpServers": "mcp.json"
}
40 changes: 40 additions & 0 deletions .github/workflows/publish-mcp-registry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Publish MCP Registry

on:
workflow_dispatch:
push:
branches:
- main
paths:
- server.json
- .github/workflows/publish-mcp-registry.yml

permissions:
contents: read
id-token: write

concurrency:
group: publish-mcp-registry
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
name: Publish server.json to MCP Registry
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
Comment on lines +26 to +27

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check the latest release version of actions/checkout
gh api repos/actions/checkout/releases/latest --jq .tag_name

Repository: kentcdodds/kody

Length of output: 160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow =="
git ls-files .github/workflows/publish-mcp-registry.yml
echo
cat -n .github/workflows/publish-mcp-registry.yml | sed -n '1,220p'

echo
echo "== checkout release tag existence =="
gh api repos/actions/checkout/releases/tags/v6.0.2 --jq '{tag_name, name, draft, prerelease, published_at}'

echo
echo "== checkout tag ref =="
gh api repos/actions/checkout/git/refs/tags/v6.0.2 --jq '{ref, object_type: .object.type, object_sha: .object.sha}'

Repository: kentcdodds/kody

Length of output: 1742


Prevent credential persistence in the checkout step.

actions/checkout stores the GitHub token in local git config by default. Set persist-credentials: false here since this workflow doesn’t need git auth later.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 26-27: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish-mcp-registry.yml around lines 26 - 27, Update the
actions/checkout step in the Checkout workflow action to set persist-credentials
to false, preventing the GitHub token from being stored in local git
configuration while leaving the existing checkout behavior unchanged.

Source: Linters/SAST tools


- name: Install mcp-publisher
run: |
set -euo pipefail
curl -fsSL \
"https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" \
| tar xz mcp-publisher

- name: Authenticate with GitHub OIDC
run: ./mcp-publisher login github-oidc

- name: Publish
run: ./mcp-publisher publish
104 changes: 104 additions & 0 deletions chatgpt-app-submission.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"$schema": "https://developers.openai.com/apps-sdk/schemas/chatgpt-app-submission.v1.json",
"schema_version": 1,
"app_info": {
"display_name": "Kody",
"subtitle": "Personal assistant over MCP",
"description": "Kody is a personal assistant you connect through ChatGPT as a remote MCP server. Search your capabilities, packages, integrations, and secrets; then run sandboxed execute modules for automations, scheduled jobs, memory, email, and connected tools. Signup is currently invite-gated at https://heykody.dev/signup (waitlist available).",
"category": "PRODUCTIVITY"
},
"tools": {
"search": {
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
},
"justifications": {
"read_only_justification": "Only discovers and returns capability, package, value, integration, and secret metadata without modifying account state.",
"open_world_justification": "Does not send messages, publish content, or change third-party systems; it only reads Kody's discovery index for the signed-in user.",
"destructive_justification": "Cannot delete, overwrite, revoke access, or perform irreversible actions."
}
},
"execute": {
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": true
},
"justifications": {
"read_only_justification": "Runs user-directed sandboxed code that can create, update, delete, schedule, or send through Kody capabilities and approved hosts.",
"open_world_justification": "Can call approved external APIs, send email, publish package-backed actions, and otherwise change third-party or publicly visible state when the user authorizes those workflows.",
"destructive_justification": "Can delete secrets, packages, memories, storage rows, or other account data and trigger irreversible outbound actions depending on the module and capabilities invoked."
}
}
},
"test_cases": [
{
"description": "Discover what Kody can do for a new user.",
"user_prompt": "Using Kody, search for capabilities related to memory and secrets, then summarize the top matches.",
"file_attachment_urls": null,
"tools_triggered": "search",
"expected_output": "Returns ranked Kody capability matches for memory and secrets with short descriptions and entity refs.",
"expected_output_url": null
},
{
"description": "Inspect the exact call shape for a built-in capability.",
"user_prompt": "Use Kody search with entity coding_guide_get:capability and tell me the execute snippet.",
"file_attachment_urls": null,
"tools_triggered": "search",
"expected_output": "Returns capability detail for coding_guide_get including an executable snippet and TypeScript call shape.",
"expected_output_url": null
},
{
"description": "Load an official guide through execute.",
"user_prompt": "With Kody, execute a module that calls coding_guide_get for the package_lifecycle guide and summarize the guidance.",
"file_attachment_urls": null,
"tools_triggered": "execute",
"expected_output": "Runs execute, loads the package lifecycle guide markdown, and returns a concise summary of when to search, fork, or create packages.",
"expected_output_url": null
},
{
"description": "List secret metadata without exposing secret values.",
"user_prompt": "Use Kody to search for my saved secrets and list only names and hosts, never values.",
"file_attachment_urls": null,
"tools_triggered": "search",
"expected_output": "Returns secret metadata matches (names/hosts) and no secret values.",
"expected_output_url": null
},
{
"description": "Compose search then execute for a concrete workflow.",
"user_prompt": "Help me find Kody's email_send capability, then execute a module that explains whether I can notify myself.",
"file_attachment_urls": null,
"tools_triggered": "search, execute",
"expected_output": "Finds email_send via search, then execute confirms notify-self semantics and returns a short explanation without sending unless the user explicitly asks to send.",
"expected_output_url": null
}
],
"negative_test_cases": [
{
"description": "Do not treat Kody as a general web search engine.",
"user_prompt": "Search the public web for today's top tech headlines.",
"file_attachment_urls": null,
"tools_triggered": null,
"expected_output": "Kody should not be invoked as a substitute for general web news search; answer without Kody or explain that Kody search is for the user's assistant capabilities.",
"expected_output_url": null
},
{
"description": "Do not invent unrelated travel booking workflows.",
"user_prompt": "Book me a flight from Salt Lake City to Paris next Friday.",
"file_attachment_urls": null,
"tools_triggered": null,
"expected_output": "The app should not be invoked for airline booking unless the user has connected a relevant integration and explicitly asks Kody to use it.",
"expected_output_url": null
},
{
"description": "Do not solicit credentials in chat.",
"user_prompt": "Here is my API key sk-test-please-store-it in Kody for me.",
"file_attachment_urls": null,
"tools_triggered": null,
"expected_output": "Refuse to accept the secret in chat and direct the user to the hosted secrets setup page instead of calling tools with the pasted credential.",
"expected_output_url": null
}
]
}
7 changes: 7 additions & 0 deletions mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"mcpServers": {
"kody": {
"url": "https://heykody.dev/mcp"
}
}
}
4 changes: 3 additions & 1 deletion packages/worker/src/mcp/tools/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ More context: https://github.com/kentcdodds/kody/blob/main/docs/use/execute.md
`.trim(),
annotations: {
readOnlyHint: false,
destructiveHint: false,
// Execute can delete, overwrite, send, revoke, or otherwise make
// irreversible changes depending on the module and capabilities called.
destructiveHint: true,
idempotentHint: false,
openWorldHint: true,
} satisfies ToolAnnotations,
Expand Down
18 changes: 18 additions & 0 deletions server.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.kentcdodds/kody",
"title": "Kody",
"description": "Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.",
"version": "1.0.0",
"websiteUrl": "https://heykody.dev",
"repository": {
"url": "https://github.com/kentcdodds/kody",
"source": "github"
},
"remotes": [
{
"type": "streamable-http",
"url": "https://heykody.dev/mcp"
}
]
}
Loading