Announcing CIMD support for MCP Client registration
Learn more

1Password MCP vs 1Password API for AI Agents (2026)

Srinivas Karre
Founding Engineer

1Password gives an AI agent several surfaces, and it has drawn a hard line between them: two official MCP servers that never return a secret, a Connect REST API and service accounts that hand values to code, and an Events Reporting API that tells you what happened to those values afterward. They overlap less than any other tool in this series. This guide compares what each path lets an agent do, why a secret must never reach model context, and how to run a security agent across many customer accounts in production.

TL;DR

  • 1Password ships two official MCP servers, and neither returns a secret. The Environments MCP server runs locally inside the 1Password desktop app over stdio with 8 tools, and its docs state it "cannot return secret values stored in 1Password to the client." The SaaS Manager MCP server at https://mcp.1password.com/trelica/mcp is remote and read-only, covering SaaS app inventory and license data. 1Password's stated position is that it "will not use MCP to expose raw credentials or secrets."
  • The direct API is really three APIs. The Connect server REST API is self-hosted and returns item field values, including passwords. Service accounts with the SDKs and CLI resolve secrets per vault, with immutable read_items, write_items, and share_items permissions. The Events Reporting API returns audit events, item usages, and sign-in attempts, never item contents, at 600 requests per minute and 30,000 per hour.
  • Every API path uses a bearer token with no OAuth flow. Connect tokens can reach up to 100 vaults and expire after 30, 90, or 180 days. Events Reporting tokens are issued by an owner or administrator, and their default expiry is "Never."
  • MCP is the right path for a developer whose coding agent needs to wire up .env files without ever seeing the values. The API is the right path for headless agents that watch who revealed, exported, or shared credentials, review failed sign-ins, and audit vault permission changes across customer accounts.
  • Scalekit's onepassword connector targets the Events Reporting API with 4 read-only tools and stores each customer's Events Reporting token in the token vault, so the MCP vs API decision doesn't change your auth infrastructure, and no tool in it can put a secret into model context.

The decision your 1Password agent forces first

Your agent needs to work with 1Password in your customers' accounts. Maybe it answers "who revealed the production database password last night," flags a burst of mfa_failed sign-ins from a new country, or checks that a departing contractor lost vault access. Maybe a developer wants their coding agent to set up environment variables without pasting keys into chat. 1Password now ships official Model Context Protocol (MCP) servers, publishes a Connect REST API, service accounts with SDKs, and an Events Reporting API. They overlap less than in any other tool in this series, because 1Password has drawn a hard line around what a model may see. Here's how to pick.

What 1Password MCP and 1Password API actually are

1Password MCP

There are two official servers, and they solve different problems.

The 1Password Environments MCP server runs locally as part of the 1Password desktop app. Clients launch it with the 1password-mcp command over stdio; remote-only MCP clients are not supported. It exposes 8 tools: authenticate, list_environments, create_environment, rename_environment, list_variables, append_variables, create_local_env_file, and list_local_env_files. The desktop app shows an authorization prompt when a client connects or calls a tool that needs per-Environment approval, and that approval holds until 1Password locks. The server can see Environment and variable names, but it never returns stored values. 1Password's August 2026 update put it on the Cursor Marketplace and describes it as "keeping secret values outside the AI model's context." The Claude Code and Cursor plugins that configure it are marked Beta.

The SaaS Manager MCP server (formerly Trelica) is remote at https://mcp.1password.com/trelica/mcp, or https://mcp.1password.eu/trelica/mcp for EU tenants, and "only allows read-only actions." It authenticates with a bearer token that you get by exchanging client credentials at /connect/token; the token lasts about an hour and must be regenerated manually, and SaaS Manager does not currently support OAuth Dynamic Client Registration. A local sm-mcp variant can enable writes with --enable-writes. The docs do not list individual tool names; 1Password's blog post on where MCP fits describes the data as SaaS application lists, owners, user-to-application mappings, and license usage.

Neither server exposes vault items. That is policy, not a gap waiting to be filled. Community MCP servers that wrap the 1Password CLI and return item values exist on public registries; they are not 1Password products.

1Password API

The Connect server REST API runs in your infrastructure. It covers vaults, items, files, and API activity: GET /v1/vaults, GET /v1/vaults/{vaultUUID}/items/{itemUUID}, POST, PUT, PATCH, and DELETE on items, and GET /v1/activity. The item response carries field values, including a password field's value. Requests use Authorization: Bearer <access_token>, with tokens scoped to specific vaults.

Service accounts authenticate the 1Password SDKs (Go, Python, JavaScript) and CLI with a token that holds per-vault read_items, write_items, or share_items permissions. 1Password's own agentic AI guidance recommends this path: a dedicated vault, a read-only service account, and secret reference URIs resolved at runtime.

The Events Reporting API exposes GET /api/v2/auth/introspect, POST /api/v2/auditevents, POST /api/v2/itemusages, and POST /api/v2/signinattempts against a regional base URL such as https://events.1password.com. A v3 beta adds GET /api/v3/auditevents. Its schemas reference items by vault_uuid and item_uuid and carry no item contents.

Comparing them where it matters for agents

What your agent can actually do

Capability
1Password MCP (Environments, SaaS Manager)
1Password API (Connect, service accounts, Events Reporting)
Read a secret value
By design; the Environments server "cannot return secret values"
Yes, Connect GET /v1/vaults/{vaultUUID}/items/{itemUUID}; SDK secret references with read_items
Create, update, or delete vault items
No
Yes, Connect POST, PUT, PATCH, DELETE; service accounts with write_items
Manage Environments and variable names
Yes, create_environment, rename_environment, list_environments, list_variables, append_variables
Limited: service accounts can only be granted read access to Environments
Write a local .env file mount
Yes, create_local_env_file, list_local_env_files (Mac and Linux)
No REST equivalent; the CLI injects at runtime instead
SaaS app inventory and license usage
Yes, SaaS Manager MCP, read-only
SaaS Manager's client-credentials API; not covered by the Scalekit connector
Audit events: vault, group, user, SSO, MFA changes
No
Yes, Scalekit onepassword_list_audit_events (requires the auditevents feature)
Item usage: fill, reveal, secure-copy, export, share, server-fetch
No
Yes, Scalekit onepassword_list_item_usages (requires itemusages)
Sign-in attempts with category, type, client, and location
No
Yes, Scalekit onepassword_list_sign_in_attempts (requires signinattempts)
Inspect what a token can read
No
Yes, Scalekit onepassword_get_token_info (wraps /api/v2/auth/introspect)
Remote endpoint for a hosted, multi-user agent
Limited: Environments is local stdio only; SaaS Manager is remote with an hour-long token
Yes, Events Reporting is hosted by 1Password; Connect is hosted by you

The table is lopsided on purpose. 1Password's MCP servers are built so a model can arrange secrets without holding them. Its APIs are built for code: Connect and service accounts hand values to a process, and Events Reporting tells you what happened to those values afterward. An agent that reasons over 1Password data almost always wants the third surface.

What the MCP path makes easier

Setting up secrets for a new project is the task the Environments server was built for. A developer tells Claude Code or Cursor "create a staging Environment with the Stripe and Postgres variables and mount it as .env," and the agent calls create_environment, append_variables, and create_local_env_file. The desktop app prompts once for approval. The model sees variable names and file paths. The values travel from 1Password to the mounted file without passing through the conversation. Writing the schema is the hard part. Not the API call.

The tradeoff is reach. The server runs on one person's machine, behind their desktop app and its lock state. It cannot serve a hosted agent, it cannot act for your customers, and it does nothing for security questions about who used a credential. The SaaS Manager server is remote, but it answers questions about SaaS licenses, not vault activity.

The secret-in-context problem

The sharp edge on the API path is simple to state. If a tool returns a secret, the secret is in the model's context. From there it is in the request to your model provider, in the conversation history you persist, in any tracing or eval logs, and available to every later turn, including a turn steered by a prompt injection in a document the agent read. 1Password's MCP position names the risk directly: credentials in model context make "unintended retention and uncontrolled usage" real threats.

Its own service account guidance stops short of solving this. The agentic AI post says to "pass the secrets to your agent without hardcoding," but a value passed to an agent is still a value the model can echo. Four mitigations hold up in production.

Resolve inside the tool executor. The model asks to "query the billing database"; your code resolves the op:// reference with the SDK, opens the connection, and returns rows. The model sees the reference name, never the value.

Inject into a subprocess, not the conversation. The CLI and Environments put values in a child process's environment or a mounted file that the model never reads back.

Scope the vault to the task. A service account with read_items on one dedicated vault limits the blast radius of a leak to that vault, and because its permissions are immutable, the scope cannot drift.

Watch the fetches. Item usage events with action server-fetch record every fetch by a service account or Connect server, which is how you prove what an agent's credentials touched.

None of these make returning raw values to a model safe. They make it unnecessary.

The auth path each one puts you on

On the MCP path, auth is local or manual. The Environments server trusts the desktop app's lock state and per-Environment prompts, and enterprise admins can switch the feature off under Policies > Agentic permissions. The SaaS Manager server takes a bearer token you mint from client credentials every hour or so. There is no OAuth consent flow on either, so neither gives a hosted agent a per-user grant.

On the direct API path, every surface is a bearer token, and each has its own scoping model. Connect tokens reach up to 100 vaults, cannot be edited after creation, and expire after 30, 90, or 180 days. Service account permissions, vault access, and Environment access are immutable, the token is shown once, and service accounts cannot reach Personal, Private, Employee, or the default Shared vault. Events Reporting tokens are issued by an owner or administrator under Integrations > Events Reporting, scoped to any of auditevents, itemusages, and signinattempts, and the get started guide says the expiry options are 30, 90, or 180 days with a default of "Never."

That default matters. A security agent built on Events Reporting holds a token that, unless someone changed a dropdown, never expires and reads every sign-in attempt across a customer's company, with names, emails, IP addresses, and city-level location. It does not open a vault. It is still a sensitive credential.

Both paths still need per-user isolation

In a multi-tenant B2B agent, MCP gives you a credential per user and the direct API gives you a credential per user. In neither case does the path itself solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.

1Password shifts the unit. Events Reporting tokens belong to a 1Password account, not a person, so for a security agent "per user" usually means one connected account per customer, authorized by that customer's admin. The isolation rule is the same: bind each connected account to one tenant in your system, and verify it. onepassword_get_token_info returns the token's account_uuid; record it at connect time and refuse to run if it ever changes, so a token pasted into the wrong customer's workspace fails loudly instead of reading another company's events.

Recommended reading: OAuth vs API keys for AI agents

What you own in production

On the MCP path, 1Password owns the servers and the decision about what a model may see. You own the local setup on every developer machine and, for SaaS Manager, a token refresh loop with no automation path documented. You also own the boundary: an agent with Environments access still runs shell commands, and 1Password ships agent hooks that validate mounted .env files before supported coding agents run them.

On the API path, you own schemas, pagination, retries, and the token lifecycle. Events Reporting allows 600 requests per minute and 30,000 per hour and returns 429 when you exceed it. The v2 endpoints page with a cursor: the first request sends limit (1 to 1000) and start_time, later requests send only the cursor, and each response returns cursor, has_more, and items. Omit both times and you get the last hour. The v3 beta switches to GET with page_token, and its time filters apply to when 1Password ingested an event, not when it occurred, so a poller that assumes otherwise misses late events.

If you also run Connect or service accounts, their limits differ. Service account rate limits on Business are 10,000 reads and 1,000 writes per hour per token, with a 50,000 request daily cap shared by every service account in the account; Teams gets 5,000 per day. An agent that resolves a secret per tool call burns that budget fast. Connect caches data locally and avoids most of those quotas, at the cost of a server you run.

When to use MCP, when to use the API

Use 1Password MCP when:

  • A developer in Claude Code, Cursor, or Codex wants the agent to create an Environment, add variable names, and mount a .env file for a new service, without any value entering the chat.
  • An IT or finance lead asks an assistant which SaaS apps have unused licenses or no owner, and the read-only SaaS Manager MCP answers from inventory data.
  • You are prototyping on one machine, with one person approving each Environment in the desktop app.
  • The requirement is that no secret value can ever reach a model, and you want the vendor to enforce it rather than your code.

Use the 1Password API when:

  • The agent runs headless: a scheduled review pulls onepassword_list_item_usages for the last 24 hours and flags every reveal, export, and share on items in production vaults.
  • The agent triages identity risk: onepassword_list_sign_in_attempts surfaces mfa_failed and credentials_failed attempts by user, country, and client for an on-call engineer.
  • The workflow is an access audit: onepassword_list_audit_events shows vault grant and revoke actions and user suspensions, which is how you confirm an offboarding actually removed access.
  • Your own pipeline needs a secret to call another system. Use a service account or Connect token inside the tool executor, return the result of the call, and keep the value out of the tool output.

The credential problem that exists on both paths

Both paths hand you a 1Password credential per tenant. Neither hands you a vault for it, which is an odd thing to say about a password manager. A security agent serving 50 customers is 50 Events Reporting tokens, each issued by an admin, each defaulting to no expiry, each able to read every sign-in and item usage in that customer's account. Add Connect or service account tokens for agents that act on secrets and each of those can resolve values directly. Each must be stored encrypted, kept out of logs and LLM context, replaced when it expires or the admin revokes it, and deleted when a customer churns.

The tempting shortcut is to put those tokens in your own 1Password vault and resolve them with a service account. That moves the problem without removing it: you now hold one service account token that can resolve all 50, and your agent runtime needs it.

Scalekit's onepassword connector stores each customer's Events Reporting token in the token vault and sends it with every call, so the MCP vs API decision doesn't change your auth infrastructure. Your agent passes an identifier; the token never enters the agent runtime or the LLM context.

Recommended reading: why a token vault matters for AI agent workflows

How to connect a 1Password agent with Scalekit

Scalekit's onepassword connector is an API-path connector built by Scalekit with 4 tools, all read-only: onepassword_get_token_info, onepassword_list_audit_events, onepassword_list_item_usages, and onepassword_list_sign_in_attempts. It targets the Events Reporting API and authenticates with a bearer token. There is no tool that reads, writes, or deletes vault items, so no agent built on it can be talked into returning a password.

Tool
What it returns
onepassword_get_token_info
The token's uuid, issue time, account_uuid, and enabled features
onepassword_list_audit_events
Vault, group, user, SSO, and MFA changes
onepassword_list_item_usages
Fill, reveal, secure-copy, export, share, and server-fetch on shared-vault items
onepassword_list_sign_in_attempts
Successful and failed sign-ins with client and location

The three list tools take cursor, start_time, end_time (RFC 3339), and limit. Full schemas are on the connector docs page.

Prerequisites and the connection name

In the Scalekit dashboard, go to AgentKit > Connections and create a 1Password connection. The name you give it is the connection_name your code passes, and the string must match the dashboard exactly. This is the most common integration error. Copy SCALEKIT_ENVIRONMENT_URL, SCALEKIT_CLIENT_ID, and SCALEKIT_CLIENT_SECRET from Developers > API Credentials into .env.

Each customer's owner or administrator creates the token in 1Password under Integrations, choosing an Events Reporting integration, the events it can read, and an expiry. Pick 90 or 180 days rather than the "Never" default; Scalekit will surface the expired account so you can ask for a new one.

pip install scalekit-sdk-python python-dotenv langchain-openai

Authorize each customer once

get_or_create_connected_account returns the connected account. If it is not ACTIVE, get_authorization_link returns a link to a Scalekit-hosted page where the admin pastes their Events Reporting token. The agent never sees it. The check at the end pins the connected account to one 1Password account.

import os from dotenv import load_dotenv from scalekit import ScalekitClient load_dotenv() scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) actions = scalekit_client.actions CONNECTION_NAME = "onepassword" # must match the connection name in AgentKit > Connections identifier = "tenant_acme" # your app's stable ID for this customer account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name=CONNECTION_NAME, identifier=identifier, ) print("Connect 1Password Events Reporting:", link.link) input("Press Enter after the admin has entered the token...") account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": raise RuntimeError(f"1Password is {account.connected_account.status}, not ACTIVE") token_info = actions.execute_tool( tool_name="onepassword_get_token_info", tool_input={}, connection_name=CONNECTION_NAME, identifier=identifier, ) print("1Password account:", token_info.data["account_uuid"]) print("Features:", token_info.data["features"]) # Store account_uuid against tenant_acme in your database and compare it on every run.

Retrieve the 1Password tools this customer can call

This is not a catalog load. The agent asks for the tools this connected account is authorized to call. With a 4-tool connector the point is less about token count and more about role: an identity-triage agent needs sign-in attempts and item usages, not the audit event feed that shows every vault permission change in the company. Give it two tools.

tools = actions.langchain.get_tools( identifier=identifier, connection_names=[CONNECTION_NAME], tool_names=[ "onepassword_list_sign_in_attempts", "onepassword_list_item_usages", ], page_size=100, ) tool_map = {t.name: t for t in tools} print(sorted(tool_map))

Run the agent loop

The loop runs until the model stops requesting tools. Every call executes with this customer's Events Reporting token, so the agent sees one 1Password account and only the event types the token was issued for. The results contain names, emails, IP addresses, and locations; that is personal data in model context, and your retention policy for conversation history should treat it that way.

from datetime import datetime, timedelta, timezone from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) now = datetime.now(timezone.utc) since = (now - timedelta(hours=24)).strftime("%Y-%m-%dT%H:%M:%SZ") until = now.strftime("%Y-%m-%dT%H:%M:%SZ") messages = [ SystemMessage( "You triage 1Password identity risk for one customer account. Use " "onepassword_list_sign_in_attempts and onepassword_list_item_usages with " f"start_time {since} and end_time {until}. When a response has has_more set " "to true, call the same tool again with only the cursor it returned. Report " "facts from the events only. Never guess user names, vaults, or items." ), HumanMessage( "Which users had failed sign-ins in the last 24 hours, from which countries " "and clients? Did any of those users reveal, export, or share an item in the " "same window? List them with timestamps." ), ] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: tool = tool_map.get(tc["name"]) if tool: result = tool.invoke(tc["args"]) else: result = f"Unknown tool: {tc['name']}" messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

Deterministic calls with execute_tool

For pipelines, skip the model. execute_tool runs one tool with a fixed input and returns data plus an execution_id you can log. This nightly job checks the token still belongs to the right account and has the features it needs, pages through the last 24 hours of item usages and sign-in attempts, and returns the events a security reviewer should see.

from datetime import datetime, timedelta, timezone SENSITIVE_ACTIONS = {"reveal", "export", "secure-copy", "share"} FAILED_CATEGORIES = {"credentials_failed", "mfa_failed", "sso_failed", "firewall_failed"} def fetch_all(tool_name: str, identifier: str, start_time: str, end_time: str) -> list: """Page through an Events Reporting feed. After the first page, send only the cursor.""" events, cursor = [], None while True: if cursor: tool_input = {"cursor": cursor} else: tool_input = {"start_time": start_time, "end_time": end_time, "limit": 1000} page = actions.execute_tool( tool_name=tool_name, tool_input=tool_input, connection_name=CONNECTION_NAME, identifier=identifier, ) print(tool_name, page.execution_id) events.extend(page.data.get("items") or []) if not page.data.get("has_more"): return events cursor = page.data["cursor"] def nightly_access_review(identifier: str, expected_account_uuid: str) -> dict: info = actions.execute_tool( tool_name="onepassword_get_token_info", tool_input={}, connection_name=CONNECTION_NAME, identifier=identifier, ) if info.data["account_uuid"] != expected_account_uuid: raise RuntimeError(f"{identifier} is connected to the wrong 1Password account") missing = {"itemusages", "signinattempts"} - set(info.data.get("features", [])) if missing: raise RuntimeError(f"Events Reporting token lacks features: {sorted(missing)}") now = datetime.now(timezone.utc) start = (now - timedelta(hours=24)).strftime("%Y-%m-%dT%H:%M:%SZ") end = now.strftime("%Y-%m-%dT%H:%M:%SZ") usages = fetch_all("onepassword_list_item_usages", identifier, start, end) sign_ins = fetch_all("onepassword_list_sign_in_attempts", identifier, start, end) flagged_usages = [ { "time": u["timestamp"], "user": u["user"]["email"], "action": u["action"], "vault_uuid": u["vault_uuid"], "item_uuid": u["item_uuid"], "ip": u["client"]["ip_address"], } for u in usages if u["action"] in SENSITIVE_ACTIONS ] failed_sign_ins = [ { "time": s["timestamp"], "user": s["target_user"]["email"], "category": s["category"], "type": s["type"], "country": s["country"], } for s in sign_ins if s["category"] in FAILED_CATEGORIES ] return {"flagged_usages": flagged_usages, "failed_sign_ins": failed_sign_ins} report = nightly_access_review(identifier, os.environ["ONEPASSWORD_ACCOUNT_UUID"]) print(len(report["flagged_usages"]), "sensitive item actions") print(len(report["failed_sign_ins"]), "failed sign-ins")

Item usage events report vault_uuid and item_uuid, not item names, and the Events Reporting API has no lookup for them. Keep a mapping of the vaults you care about, such as production infrastructure, in your own config and filter on vault_uuid. The same job extends to offboarding: run onepassword_list_audit_events for the departure window and confirm a revoke or user suspension event exists for the person who left. Neither 1Password MCP server can answer either question.

Multi-tool, multi-tenant 1Password agents on a virtual MCP server

The onepassword connector is small, so tool bloat is not the risk here. Overreach and tenant mixing are. A security agent rarely works from 1Password alone: it reads sign-in attempts, then posts to Slack, then opens a ticket. If that agent connects to a generic MCP server per app, you are managing which customer's 1Password token sits behind which endpoint, and a single misrouted session reads another company's sign-in history. A Scalekit virtual MCP server declares exactly which tools an agent role can see, and session tokens keep each run bound to one customer's connected accounts. Docs: set up a virtual MCP server.

Create the server once per agent role

from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = actions.mcp.create_config( name="onepassword-identity-triage", description="Reviews 1Password sign-ins and item usage and posts findings to Slack", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="onepassword", tools=[ "onepassword_list_sign_in_attempts", "onepassword_list_item_usages", ], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_send_message"], ), ], ) print(vmcp.config.id, vmcp.config.mcp_server_url)

Mint a session token per customer, per run

One server definition serves every customer. Before each run, check that the customer's accounts are active and mint a short-lived session token scoped to them. Any MCP client that speaks Streamable HTTP can connect; this example uses langchain-mcp-adapters (pip install langchain-mcp-adapters) and passes the token as a Bearer header.

import asyncio from datetime import timedelta from langchain_mcp_adapters.client import MultiServerMCPClient config_id = vmcp.config.id mcp_server_url = vmcp.config.mcp_server_url tenant_id = "tenant_acme" accounts = actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier=tenant_id, include_auth_link=True, ) not_ready = [ a for a in accounts.connected_accounts if str(a.connected_account_status).upper() != "ACTIVE" ] for a in not_ready: print(f"{a.connection_name} is {a.connected_account_status}: {a.authentication_link}") if not_ready: raise RuntimeError("Connect the accounts above before starting this run") session_token = actions.mcp.create_session_token( mcp_config_id=config_id, identifier=tenant_id, expiry=timedelta(minutes=30), ).token async def load_tools(): client = MultiServerMCPClient( { "scalekit": { "transport": "streamable_http", "url": mcp_server_url, "headers": {"Authorization": f"Bearer {session_token}"}, } } ) return await client.get_tools() mcp_tools = asyncio.run(load_tools()) print([t.name for t in mcp_tools])

The agent sees three tools and one customer. The endpoint is static; the identity is per-user. Unlike 1Password's Environments server, this endpoint is remote, so a hosted agent can use it, and unlike a self-built wrapper over Connect, it has no tool that can return a vault item.

Observability: every 1Password action tied to a user

Every execute_tool call returns an execution_id, and every execution is attributed to a connected account, which maps to one of your customers. When a customer's security lead asks which agent run read their sign-in history and when, the answer is a lookup, not an investigation.

The loop closes on the 1Password side. If you also give agents service account or Connect tokens to act on secrets, every fetch shows up in that customer's item usage feed with action server-fetch. Your Events Reporting agent can audit your secret-fetching agents, and your execution log shows which run and which prompt led to each fetch.

A shared credential breaks that. If every customer's events flow through one Events Reporting token, there is no such thing as one customer's events, and if every agent fetches secrets through one service account, 1Password attributes every server-fetch to that account. Shared credentials are a single-user solution. They do not survive a second user.

Recommended reading: audit trails for agent auth

Which one to build against

If your agent is a developer's assistant in Claude Code, Cursor, or Codex that sets up Environments and .env mounts, or an IT assistant asking SaaS Manager about licenses, use 1Password's MCP servers: they are built so the model never holds a value, and that is the right default. If your agent runs unattended and reasons about who used which credential, who failed to sign in, and whether access was revoked, build against the Events Reporting API. If your agent needs a secret to do its job, resolve it with a service account or Connect token inside your tool code and never return it to the model. Either way, you hold one long-lived, admin-issued 1Password token per customer, and that's what needs production-grade infrastructure.

FAQs

Does 1Password have an official MCP server?

It has two. The Environments MCP server runs locally inside the 1Password desktop app over stdio with 8 tools for creating Environments, adding variable names, and mounting .env files, and its docs state it cannot return secret values to the client. The SaaS Manager MCP server at https://mcp.1password.com/trelica/mcp is remote, read-only, and covers SaaS app inventory and license data. 1Password's stated position is that it will not use MCP to expose raw credentials.

Can an AI agent read a password from 1Password?

Not through either official MCP server. The Connect server REST API and service accounts with the SDKs and CLI do return item field values, including passwords, to code. If an agent needs a secret to do its job, resolve it with a service account or Connect token inside the tool executor, use it to make the call, and return the result rather than the value, so the secret never enters model context.

What does the 1Password Events Reporting API return?

Audit events such as vault, group, user, SSO and MFA changes; item usages such as fill, reveal, secure-copy, export, share and server-fetch; and sign-in attempts with category, type, client and location. It references items by vault_uuid and item_uuid and never carries item contents. Limits are 600 requests per minute and 30,000 per hour, with cursor pagination where later requests send only the cursor.

How do 1Password API tokens expire?

Connect tokens reach up to 100 vaults and expire after 30, 90, or 180 days. Service account tokens are shown once with immutable per-vault read_items, write_items, and share_items permissions. Events Reporting tokens are issued by an owner or administrator with the same expiry options, but their default is Never, so a security agent can end up holding a non-expiring token that reads every sign-in attempt in a customer's company unless someone changes the dropdown.

When should an agent use the 1Password API instead of MCP?

When it runs headless and reasons about what happened to credentials: flagging every reveal, export, and share on production vault items in the last 24 hours, surfacing mfa_failed and credentials_failed sign-ins by user, country and client, or confirming that an offboarding produced a vault revoke or user suspension event. Neither MCP server can answer those questions.

How does Scalekit connect an AI agent to 1Password?

The onepassword connector targets the Events Reporting API with 4 read-only tools: onepassword_get_token_info, onepassword_list_audit_events, onepassword_list_item_usages, and onepassword_list_sign_in_attempts. Each customer's admin pastes their Events Reporting token once, Scalekit stores it in the token vault and sends it with every call, and no tool in the connector can put a secret into model context.

Build your 1Password agent with Scalekit

Browse the Scalekit 1Password connector and the 1Password connector docs with the full tool list. See Scalekit pricing, or talk to us.

No items found.
On this page
Share this article
Scalekit
Secret-free tools

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.