-
Notifications
You must be signed in to change notification settings - Fork 3
Add MCP integration and Developer Environments skill (v1.2.0) #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
bc1eb3e
081607a
c548302
f542a29
e86af79
4188d5a
7a4b2a2
8cde9db
36a788e
aae359b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| .DS_Store | ||
|
|
||
| # Environment files (keep templates committable) | ||
| .env | ||
| .env.* | ||
| !.env.example | ||
| !.env.sample | ||
| !.env.template | ||
| !.env.dist | ||
|
|
||
| # Python | ||
| __pycache__/ | ||
| *.py[cod] | ||
|
|
||
| # Local dev hook wiring (use when team policy blocks local plugin imports) | ||
| .cursor/hooks.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,21 @@ | ||
| # 1Password Plugin for Cursor | ||
|
|
||
| The official [1Password](https://1password.com) plugin for [Cursor](https://cursor.com). It brings 1Password's secret management capabilities directly into your editor, helping you develop securely without leaving your workflow. | ||
| The official [1Password](https://1password.com) plugin for [Cursor](https://cursor.com). It ships three pieces that work together: **hooks** that validate locally mounted `.env` files, an **agent skill** with the complete Developer Environment workflow, and **MCP configuration** for the 1Password desktop app server. Secret values stay in 1Password — the agent sees variable names and mount paths, not secret contents. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we plan on taking this approach for other plugins, or just Cursor? Asking because it takes a different approach than our other MCP server instructions, which are only for the MCP server. The agent skill is also new to me. I'm wondering if we need to rethink our MCP server docs more comprehensively to support this. Alternatively, if it's possible to install the MCP server alone OR install this package, maybe this plugin can have its own, standalone page. |
||
|
|
||
| Install the **plugin** (not a hand-configured MCP entry alone). The bundled `1password-environments` skill is the authoritative agent workflow; the MCP server's built-in documentation resources cover tool basics only and omit import-and-mount steps. | ||
|
|
||
| For more on 1Password's developer tools, see the [1Password Developer Documentation](https://developer.1password.com). | ||
|
|
||
| ## Requirements | ||
|
|
||
| - [1Password](https://1password.com) subscription | ||
| - [1Password for Mac or Linux](https://1password.com/downloads) | ||
| - [1Password for Mac](https://1password.com/downloads) (this plugin targets **macOS**) | ||
| - [Cursor](https://cursor.com) | ||
| - [sqlite3](https://www.sqlite.org/) installed and available in your `PATH` (pre-installed on macOS; install via your package manager on Linux) | ||
|
|
||
| Additional requirements by feature: | ||
|
|
||
| - **Hooks** — [sqlite3](https://www.sqlite.org/) installed and available in your `PATH` (pre-installed on macOS; install via your package manager on Linux) | ||
| - **MCP** — 1Password Labs **MCP Server** experiment enabled in the desktop app (`onepassword://settings/labs`). If the setting is missing, your account may not have the `ai-local-mcp-server` feature flag. | ||
|
|
||
| > **Note:** 1Password Environments local `.env` mounts only apply on **macOS and Linux**. **`hooks.json`** invokes **`./scripts/validate-mounted-env-files`** with no extension. On **macOS / Linux**, that runs the **Bash** script. On **Windows** the shell looks for a real file by trying suffixes from **`PATHEXT`** until one matches on disk. That yields **`validate-mounted-env-files.cmd`**, which returns **`allow`** and skips validation so agent shells are not blocked. | ||
|
|
||
|
|
@@ -24,14 +30,32 @@ Before using this plugin, you'll need to configure your secrets in 1Password: | |
|
|
||
| ### Step 2: Install the plugin | ||
|
|
||
| Install from the [Cursor Marketplace](https://cursor.com/marketplace): | ||
| Install from the [Cursor Marketplace](https://cursor.com/marketplace). This registers hooks, the `1password-environments` agent skill, and `mcp.json` together. Do not add the 1Password MCP server manually in user settings instead of installing the plugin — agents will get MCP tools without the skill workflow. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this just mean they'll get the MCP server only and not the hook? Asking because we have a manual tab in the docs that instructs people to do just this, so I want to make sure nothing else is missing: https://www.1password.dev/environments/mcp-server#other |
||
|
|
||
| 1. Open **Cursor Settings** > **Plugins**. | ||
| 2. Search for **1password**. | ||
| 3. Click **Install**. | ||
|
|
||
| Or use the command palette: `Ctrl+Shift+P` (or `Cmd+Shift+P` on macOS) > **Plugins: Install Plugin** > search for `1password`. | ||
|
|
||
| Or install directly: | ||
|
|
||
| ``` | ||
| /add-plugin 1password | ||
| ``` | ||
|
|
||
| ### Step 3: Enable MCP in 1Password (required for Environment management) | ||
|
|
||
| Enable the **MCP Server** experiment in the 1Password desktop app: open **Settings → Labs** (or use `onepassword://settings/labs`) and turn on **MCP Server**. The plugin's `mcp.json` connects Cursor to that server after this step. | ||
|
|
||
| The MCP server binary on macOS: | ||
|
|
||
| ```text | ||
| /Applications/1Password.app/Contents/MacOS/onepassword-mcp | ||
| ``` | ||
|
|
||
| On Linux, see the [1Password MCP server documentation](https://www.1password.dev/environments/mcp-server) for the binary path on your platform. | ||
|
|
||
|
scottisloud marked this conversation as resolved.
|
||
| ## Features | ||
|
|
||
| ### Hooks | ||
|
|
@@ -40,7 +64,7 @@ Or use the command palette: `Ctrl+Shift+P` (or `Cmd+Shift+P` on macOS) > **Plugi | |
|
|
||
| Validates locally mounted `.env` files from [1Password Environments](https://developer.1password.com/docs/environments) before any shell command executes. When required environment files are missing, disabled, or misconfigured, the hook blocks execution and surfaces actionable error messages so the Cursor Agent can guide you to a fix. | ||
|
|
||
| This hook was originally developed in the [1Password Cursor Hooks](https://github.com/1Password/cursor-hooks) repository. For the full setup guide, see [Validate local `.env` files with Cursor Agent](https://developer.1password.com/docs/environments/cursor-hook-validate/). | ||
| This hook was originally developed in the [1Password Agent Hooks](https://github.com/1Password/agent-hooks) repository. For the full setup guide, see [Validate local `.env` files with Cursor Agent](https://developer.1password.com/docs/environments/cursor-hook-validate/). | ||
|
|
||
| **How it works:** | ||
|
|
||
|
|
@@ -122,26 +146,66 @@ DEBUG=1 echo '{"command": "echo test", "workspace_roots": ["/path/to/your/projec | |
|
|
||
| When not running in debug mode, the hook writes logs to `/tmp/1password-cursor-hooks.log`. Log entries include timestamps and details about 1Password queries, validation results, and permission decisions. | ||
|
|
||
| ### MCP and agent skill | ||
|
|
||
| The plugin connects Cursor to the local 1Password MCP server and bundles the **`1password-environments`** skill (`skills/1password-environments/SKILL.md`). Agents should read that skill before calling MCP tools — it defines the complete workflow for importing a plain `.env` file, appending variables, and mounting at the source path. The MCP server's built-in docs cover tool basics but omit those import-and-mount steps. | ||
|
|
||
| See `skills/1password-environments/reference.md` for setup, mount conflicts, and shell validation details. | ||
|
|
||
| #### Example prompts | ||
|
|
||
| - "List my 1Password Environments" | ||
| - "Mount my staging Environment as `.env` in this repo" | ||
| - "What variables are in my production Environment?" | ||
| - "Create a new Environment called `my-app-dev`" | ||
| - "Create an Environment from my project `.env` file" | ||
| - "Import `.env` into 1Password and mount it here" | ||
| - "Add a placeholder for my OpenAI API key" | ||
|
|
||
| #### MCP tools | ||
|
|
||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `authenticate` | Authenticate with the 1Password desktop app; returns `accountId` | | ||
| | `list_environments` | List Developer Environments for an account | | ||
| | `create_environment` | Create a new Developer Environment | | ||
| | `rename_environment` | Rename an existing Developer Environment | | ||
| | `list_variables` | List variable names in an Environment (no values) | | ||
| | `append_variables` | Add or update Environment variables | | ||
| | `create_local_env_file` | Mount an Environment as a local `.env` file | | ||
| | `list_local_env_files` | List existing local `.env` mounts for an Environment | | ||
|
|
||
| Confirm the MCP server is connected in **Cursor Settings → MCP** after installing the plugin and enabling the Labs experiment in 1Password. | ||
|
|
||
| ## Plugin Structure | ||
|
|
||
| ``` | ||
| 1password/ | ||
| cursor-plugin/ | ||
| ├── .cursor-plugin/ | ||
| │ └── plugin.json # Plugin manifest | ||
| ├── hooks/ | ||
| │ └── hooks.json # Hook event configuration | ||
| │ └── hooks.json # beforeShellExecution mount validation | ||
| ├── skills/ | ||
| │ └── 1password-environments/ | ||
| │ ├── SKILL.md # Agent skill for MCP workflows | ||
| │ └── reference.md # Setup, mount conflict, and troubleshooting | ||
| ├── mcp.json # MCP server configuration | ||
| ├── assets/ | ||
| │ └── logo.svg # Plugin logo | ||
| │ ├── logo.svg # Plugin logo | ||
| │ └── icon.svg | ||
| ├── scripts/ | ||
| │ ├── lib/ | ||
| │ │ └── telemetry.sh # Opt-in telemetry helpers for the validation hook | ||
| │ ├── validate-mounted-env-files # Bash hook (macOS / Linux) | ||
| │ └── validate-mounted-env-files.cmd # Windows cmd wrapper returns allow (validation skipped) | ||
| ├── LICENSE | ||
| └── README.md | ||
| ``` | ||
|
|
||
|
|
||
| ## Telemetry | ||
|
|
||
| The plugin emits **opt-in** telemetry so 1Password can understand plugin adoption and the prevalence of common failure modes (missing files, disabled mounts). Two event types are emitted: | ||
| The validation hook emits **opt-in** telemetry so 1Password can understand plugin adoption and the prevalence of common failure modes (missing files, disabled mounts). Two event types are emitted: | ||
|
|
||
| - `agent_hook_execution` — fired once per hook invocation; carries the hook name, plugin version, client (`cursor`), bucketed duration, decision (`allow`/`deny`), reason for deny, validation mode (`default`/`configured`), and a count of mounts checked. | ||
| - `agent_hook_install` — fired once per `(hook_name, plugin_version)` on the first hook run after installation or upgrade; `install_method` is `plugin_marketplace`. | ||
|
|
@@ -159,6 +223,7 @@ The plugin emits **opt-in** telemetry so 1Password can understand plugin adoptio | |
| ## Resources | ||
|
|
||
| - [Validate local `.env` files with Cursor Agent](https://developer.1password.com/docs/environments/cursor-hook-validate/) — full setup guide on the 1Password Developer site | ||
| - [1Password MCP server documentation](https://www.1password.dev/environments/mcp-server) | ||
| - [1Password Agent Hooks](https://github.com/1Password/agent-hooks) — the original hooks repository this plugin is based on | ||
| - [1Password Environments](https://developer.1password.com/docs/environments) — documentation for 1Password's environment and secrets management | ||
| - [1Password Local `.env` Files](https://developer.1password.com/docs/environments/local-env-file) — how local `.env` file mounting works | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "mcpServers": { | ||
| "1password": { | ||
| "command": "/Applications/1Password.app/Contents/MacOS/onepassword-mcp", | ||
| "args": [] | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,24 +59,14 @@ get_telemetry_dir() { | |
| echo "${HOME}/.config/1Password/data/hook-events" | ||
| } | ||
|
|
||
| # Emit the `,"ts":<epoch_ms>` JSON fragment stamping when the event was | ||
| # produced, or an empty string if the clock is unreadable. | ||
| ts_json_fragment() { | ||
| local ts | ||
| ts=$(current_time_ms) | ||
| if [[ "$ts" =~ ^[0-9]+$ ]]; then | ||
| printf ',"ts":%s' "$ts" | ||
| fi | ||
| } | ||
|
Comment on lines
-62
to
-70
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we wanted to revert the telemetry timestamp changes in this file |
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you mean to remove this from the telemetry script? |
||
| # Check whether the 1Password app has signaled that telemetry is enabled. | ||
| # Returns 0 (true) if the signal file exists, 1 (false) otherwise. | ||
| telemetry_consent_enabled() { | ||
| [[ -f "${HOME}/.config/1Password/telemetry-enabled" ]] | ||
| } | ||
|
|
||
| # Append a single JSON line to the events.jsonl file. | ||
| # Checks consent and enforces a 1MB file size cap (drop-newest). | ||
| # Checks consent and enforces a 1MB file size cap. | ||
| write_telemetry_event() { | ||
| local json_line="$1" | ||
| local event_dir | ||
|
|
@@ -152,11 +142,8 @@ write_execution_event() { | |
| local duration_bucket | ||
| duration_bucket=$(bucket_duration_ms "$duration_ms") | ||
|
|
||
| local ts_field | ||
| ts_field=$(ts_json_fragment) | ||
|
|
||
| local json_line | ||
| json_line="{\"schema\":\"agent_hook_execution\",\"hook_name\":\"${escaped_hook_name}\",\"hook_version\":\"${escaped_hook_version}\",\"client\":\"${escaped_client}\",\"event_type\":\"${escaped_event_type}\",\"decision\":\"${decision}\",\"deny_reason\":${deny_reason_json},\"duration_bucket\":\"${duration_bucket}\",\"mode\":${mode_json},\"mount_count\":${mount_count_json}${ts_field}}" | ||
| json_line="{\"schema\":\"agent_hook_execution\",\"hook_name\":\"${escaped_hook_name}\",\"hook_version\":\"${escaped_hook_version}\",\"client\":\"${escaped_client}\",\"event_type\":\"${escaped_event_type}\",\"decision\":\"${decision}\",\"deny_reason\":${deny_reason_json},\"duration_bucket\":\"${duration_bucket}\",\"mode\":${mode_json},\"mount_count\":${mount_count_json}}" | ||
|
|
||
| write_telemetry_event "$json_line" | ||
| } | ||
|
|
@@ -173,11 +160,8 @@ write_install_event() { | |
| escaped_hook_name=$(escape_json_string "$hook_name") | ||
| escaped_hook_version=$(escape_json_string "$hook_version") | ||
|
|
||
| local ts_field | ||
| ts_field=$(ts_json_fragment) | ||
|
|
||
| local json_line | ||
| json_line="{\"schema\":\"agent_hook_install\",\"client\":\"${escaped_client}\",\"hook_name\":\"${escaped_hook_name}\",\"hook_version\":\"${escaped_hook_version}\",\"install_method\":\"${install_method}\"${ts_field}}" | ||
| json_line="{\"schema\":\"agent_hook_install\",\"client\":\"${escaped_client}\",\"hook_name\":\"${escaped_hook_name}\",\"hook_version\":\"${escaped_hook_version}\",\"install_method\":\"${install_method}\"}" | ||
|
|
||
| write_telemetry_event "$json_line" | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only asset we use but I see we add others in this PR. Does Cursor Marketplace automatically pick these other ones up?