
Clear skies for your AI agents.
One MCP URL for every agent. Access by role, plain-English rules checked before every action, every call on the record.
One URL instead of fourteen keys.
When a team adopts agents, everyone wires up their own: a server per tool, a token per server, a database URL from the wiki. Soon nobody can say who reaches payroll, and the person who left in September is still connected.
With Smartplane the file is one line. Keys stay in an encrypted vault on the server, and what each agent sees comes from who is signed in.
~/grace/project/.mcp.json
{
"mcpServers": {
"github": { "command": "npx", "args": ["@mcp/github"], "env": { "GITHUB_TOKEN": "ghp_r8Kq2vT…" } }, "github": { "GITHUB_TOKEN": "ghp_r8Kq2vT…" },Grace’s personal token, with repo and admin:org "linear": { "url": "https://mcp.linear.app/sse" }, "linear": { "url": "mcp.linear.app/sse" }, "postgres": { "command": "npx", "args": ["@mcp/postgres", "postgres://admin:pw@prod-db:5432/app"] }, "postgres": { "admin:pw@prod-db" },Production database, read and write "stripe": { "command": "npx", "args": ["@stripe/mcp"], "env": { "STRIPE_KEY": "sk_live_51Hx…" } }, "stripe": { "STRIPE_KEY": "sk_live_51Hx…" },A live key that can refund any amount "slack": { "command": "npx", "args": ["@mcp/slack"], "env": { "SLACK_BOT_TOKEN": "xoxb-2291…" } }, "slack": { "SLACK_TOKEN": "xoxb-2291…" }, "gdrive": { "command": "npx", "args": ["@mcp/gdrive"], "env": { "CREDS": "~/Downloads/creds (2).json" } }, "gdrive": { "CREDS": "creds (2).json" }, "notion": { "url": "https://mcp.notion.com/mcp" }, "notion": { "url": "mcp.notion.com" }, "sentry": { "command": "npx", "args": ["@sentry/mcp"], "env": { "SENTRY_TOKEN": "sntrys_eyJ…" } }, "sentry": { "SENTRY_TOKEN": "sntrys_eyJ…" }, "datadog": { "command": "npx", "args": ["dd-mcp"], "env": { "DD_API_KEY": "4f1c9e…" } }, "datadog": { "DD_API_KEY": "4f1c9e…" }, "jira": { "command": "uvx", "args": ["mcp-atlassian"], "env": { "JIRA_TOKEN": "ATATT3x…" } }, "jira": { "JIRA_TOKEN": "ATATT3x…" }, "snowflake": { "command": "uvx", "args": ["snowflake-mcp"], "env": { "SF_PASSWORD": "Winter2025!" } }, "snowflake": { "SF_PASSWORD": "Winter25!" },A shared password, in plain text "aws": { "command": "uvx", "args": ["aws-mcp"], "env": { "AWS_SECRET_ACCESS_KEY": "wJalr…" } }, "aws": { "AWS_SECRET_KEY": "wJalr…" }, "billing-api": { "url": "https://billing.internal/mcp", "headers": { "Authorization": "Bearer eds_7Qm…" } }, "billing-api": { "Bearer eds_7Qm…" },Edsger’s token. He left in September. "figma": { "url": "http://127.0.0.1:3845/mcp" } "figma": { "url": "127.0.0.1:3845" }"smartplane": { "url": "https://app.smartplane.dev/mcp" }Plug in what agents may use.
Integrations, databases, MCP servers, secrets and variables, added once by an admin. Each is granted to a team, a role or a person, down to a single tool.
- Shared or per person
- Connect one account for everyone, or let each person sign in with their own. Grants and rules apply either way.
- Read-only by default
- Databases answer reads unless you grant writes, and a rule can still hold a write for approval.
- Grants that expire
- Give the CI agent admin on GitHub until the migration ships on October 1. On October 1, it ends.
Resources
12
LinearConnected · shared
GitHubConnected · shared
SlackPer person
StripeConnected · shared
Notionmcp.notion.comPer personSentrymcp.sentry.devConnected · shared
- ordersPostgresRead-only
Granted toEngineering · use
- eventsClickHouseRead-only
STRIPE_KEY••••••••••••DeliverableOPENAI_API_KEY••••••••••••Gateway only
LOG_LEVELinfoREGIONeu-west-1
Keep your secrets – secret.
Smartplane stores your keys and secrets safely and hands them out only when needed, hidden from disks, logs, agent transcripts and third-party services.
Instead of giving your production keys to agents and services, give them a Smartplane key you can control, rotate and audit at any time.
Keep them safe locally.
$ smartplane run -- npm run devDelivered STRIPE_KEY, DATABASE_URL · OPENAI_API_KEY (no grant)> checkout@2.3.0 dev> node server.jsConnecting with sk_live_51H8xQ2eZvKYlo…[smartplane:STRIPE_KEY]Auth: Basic c2tfbGl2ZV81MUg4eFEyZV…[smartplane:STRIPE_KEY] base64 tooReady on http://localhost:3000Masking stops accidents: agent transcripts, logs, screen shares. It can’t hide a secret from the process you hand it to, so grant each one only what it needs.
Even in production.
On Railway, Fly or any host with a start command, the service fetches its secrets once at boot with a scoped machine token. With our Node SDK and refreshEvery, a rotated key arrives without a redeploy.
api-prod
- Start command
smartplane run -- node server.js- Variables
SMARTPLANE_TOKEN••••••••••••
Build complete · main@4f2c9e1Starting containersmartplane delivered STRIPE_KEY, DATABASE_URLServer listening on :8080- Nothing on disk
- Secrets go straight into the process environment. No .env file to commit by mistake, paste into a chat or leave on an old laptop.
- Masked in the output
- Values print as [smartplane:NAME], base64 and URL-encoded copies included, so transcripts, logs and screen shares stay clean.
- Only what you’re granted
- Grants decide who receives which secret, and every delivery goes on the audit log, per secret: who, where and when.
Rules in plain English, checked first.
Type the rule the way you’d say it in a meeting. Smartplane finds the tools it applies to, writes the check, tests it on example calls, and waits for you to switch it on.
Each rule decides what happens on a match: block the action, flag it in the log, or hold it until someone with the right role approves. Nobody approves their own request.
Say the thing, not the tool. Ask for “the todo list” and it finds your actual Todo database and pins the rule to it, so a call that only carries a page id is still caught.
Onboarding in seconds.
Added to the Platform team in Okta: GitHub, Linear and Postgres (read-only) are there before the first coffee.
- GitHubRepositories · write
- LinearIssues · read
- PostgresOrders DB · read-only
- GmailSend as team
Offboarding, instantly.
Deactivated in Okta: tokens revoked, grants removed, teams removed. The next call is refused, and logged.
- GitHubRepositories · write
- LinearIssues · read
- PostgresOrders DB · read-only
- GmailSend as team
Okta, Entra ID and Google Workspace over SSO and SCIM. Every change goes on the audit log.
Every call, on the record.
Tool calls, denials, approvals, grant changes and sign-ins go into an append-only log. Each event carries the hash of the one before it, so an edited or deleted row breaks the chain.
- 128414:02:31Call allowed
sentry__search_issuesLeila H., in ChatGPT ·{"query":"is:unresolved checkout"}Leila H., in ChatGPT02ff15 - 128314:02:27Call blocked
github__push_filesIngrid J., in VS Code · Rule: Nobody force-pushes to mainIngrid J., in VS Code0fdc7f - 128214:02:21Call allowed
stripe__list_chargesAiyana T., in Claude Code ·{"limit":20,"created":{"gte":"today"}}Aiyana T., in Claude Codefa169d - 128114:02:13Held for approval
stripe__create_refundNoa B., in VS Code · Rule: Refunds over $500 need FinanceNoa B., in VS Codeb2f38a - 128014:02:03Secret deliveredapi-prod · machine token · STRIPE_KEY to api-prod · value maskedapi-prod · machine token
857d6f - 127914:01:51Call allowed
sentry__get_issue_detailsTomasz N., in Claude Code ·{"issue":"CHECKOUT-3F2"}Tomasz N., in Claude Code67d044 - 127814:01:37Call allowed
clickhouse__queryRafael C., in VS Code ·{"sql":"SELECT count() FROM events WHERE day = today()"}Rafael C., in VS Code775b05
linear__create_issueKenji W., in ChatGPT · {"team":"ENG","title":"Retry webhook on 502"}Kenji W., in ChatGPTnotion__notion-update-pageAiyana T., in Cursor · Rule: Nobody updates the todo list in NotionAiyana T., in Cursorpostgres__queryNoa B., in VS Code · Rule: No writes to productionNoa B., in VS Codepostgres__queryCI agent · {"sql":"SELECT id, total FROM orders WHERE id = 4182"}CI agentlinear__create_issueWei C., in Cursor · {"team":"ENG","title":"Retry webhook on 502"}Wei C., in Cursorstripe__create_refundAmara O., in VS Code · Rule: Refunds over $500 need FinanceAmara O., in VS Codestripe__create_refundSupport bot · Rule: Refunds over $500 need FinanceSupport botstripe__list_chargesSofia L., in ChatGPT · {"limit":20,"created":{"gte":"today"}}Sofia L., in ChatGPTclickhouse__queryNoa B., in Cursor · {"sql":"SELECT count() FROM events WHERE day = today()"}Noa B., in Cursornotion__notion-searchTomasz N., in Cursor · {"query":"incident runbook"}Tomasz N., in Cursorgithub__get_file_contentsPriya R., in ChatGPT · {"repo":"checkout","path":"src/retry.ts"}Priya R., in ChatGPTstripe__list_chargesCI agent · {"limit":20,"created":{"gte":"today"}}CI agentpostgres__queryMateo A., in VS Code · Rule: No writes to productionMateo A., in VS Codenotion__notion-searchIngrid J., in ChatGPT · {"query":"incident runbook"}Ingrid J., in ChatGPTgithub__push_filesLeila H., in Cursor · Rule: Nobody force-pushes to mainLeila H., in Cursorpostgres__queryYusuf K., in Claude Code · {"sql":"SELECT id, total FROM orders WHERE id = 4182"}Yusuf K., in Claude Codestripe__create_refundSupport bot · Rule: Refunds over $500 need FinanceSupport botstripe__create_refundSupport bot · Rule: Refunds over $500 need FinanceSupport botstripe__list_chargesAiyana T., in ChatGPT · {"limit":20,"created":{"gte":"today"}}Aiyana T., in ChatGPTsentry__search_issuesNoa B., in ChatGPT · {"query":"is:unresolved checkout"}Noa B., in ChatGPTstripe__list_chargesIngrid J., in Claude Code · {"limit":20,"created":{"gte":"today"}}Ingrid J., in Claude Codegithub__push_filesCI agent · Rule: Nobody force-pushes to mainCI agentnotion__notion-update-pageRafael C., in ChatGPT · Rule: Nobody updates the todo list in NotionRafael C., in ChatGPTpostgres__queryYusuf K., in VS Code · {"sql":"SELECT id, total FROM orders WHERE id = 4182"}Yusuf K., in VS Codesentry__get_issue_detailsCI agent · {"issue":"CHECKOUT-3F2"}CI agentnotion__notion-fetchNoa B., in Claude Code · {"id":"Release checklist"}Noa B., in Claude Codenotion__notion-update-pageIngrid J., in Cursor · Rule: Nobody updates the todo list in NotionIngrid J., in CursorSample events, made up in your browser. No real people or data.
- Evidence an auditor can re-check
- Export any window as NDJSON with the hashes, and the chain can be verified offline. Exports are logged too.
- Values never enter the log
- A secret delivery records which secret, to whom and when. Never the value, in the log or in a trace.
Ready for your security review.
Whoever signs off on agent access, in security, IT or compliance, gets the controls they would ask for: who can reach what, how it was removed, and a record nobody can quietly edit.
- Access reviews with evidence
- A review snapshots every membership and grant and lists live machine tokens. Nobody decides on their own access, a revoke applies at once, and the decisions export as CSV.
- SOC 2 CC6.2, CC6.3
- Offboarding in one step
- Deactivate someone in your directory and one path ends it all: membership, tokens, grants, teams and personal connected accounts.
- SOC 2 CC6.2, CC6.3
- A log nobody can quietly edit
- Append-only and hash-chained per organisation, with a chain check in the dashboard and a nightly archive.
- SOC 2 CC7.2
- Least privilege, per team and action
- Grants per person, team, role or project, down to one tool, one API method or a read-only database, with an end date.
- SOC 2 CC6.3
- Secrets stay inside
- Envelope-encrypted with AES-256-GCM. No value ever reaches an agent; it leaves only if an admin marks it deliverable, and every delivery is logged.
- SOC 2 CC6.1, CC6.7
- Less data to the classifier
- The model that checks calls sees a caller’s email only when a rule is about people. Member names and emails never reach the rule compiler.
- SOC 2 P4.1
Smartplane is SOC 2-ready, not certified: each control above maps to the SOC 2 criteria beside it, and the evidence comes out of the product.
Read the security pageWorks with the agents you use.
Claude Code, Cursor, VS Code, ChatGPT and your own agents all speak MCP. Clients with MCP sign-in only need the URL: they open a browser, you sign in with your work account, and access ends when your membership does.
Claude Code
Run this in your terminal, then /mcp in Claude Code to sign in.
claude mcp add --transport http smartplane https://app.smartplane.dev/mcpCursor
Add this to .cursor/mcp.json. Cursor opens a browser to sign in.
{
"mcpServers": {
"smartplane": {
"url": "https://app.smartplane.dev/mcp"
}
}
}VS Code
Run this in your terminal. VS Code asks you to sign in on first use.
code --add-mcp '{"name":"smartplane","type":"http","url":"https://app.smartplane.dev/mcp"}'ChatGPT
In ChatGPT, open Settings, then Connectors, create one and paste the URL.
https://app.smartplane.dev/mcpAny MCP client
Any MCP client takes the URL. For CI, send a token as a bearer header.
{
"smartplane": {
"url": "https://app.smartplane.dev/mcp",
"headers": {
"Authorization": "Bearer pc_…"
}
}
}For CI and older clients, create a token. It’s shown once, stored as a hash and expires within 90 days.
Start with your own team.
Free for up to five members. Pay per member when you need SSO, SCIM and a year of audit history.
Compare plansFree
$0forever
For individuals and small teams trying governed agent access.
- Up to 5 members
- 10 connected tools and MCP servers
- Role-based grants
Team
$24per member / month
For teams rolling agents out across engineering and operations.
- Unlimited tools and MCP servers
- Team and project grants
- Unlimited rules
Enterprise
Customannual contract
For regulated organisations with procurement and compliance requirements.
- Everything in Team
- Data residency options
- Custom audit retention and SIEM streaming
Hand out one URL. Keep the keys.
Set up your first resource and rule in about ten minutes. Your team adds one line to their agent, and every call after that is cleared, held or blocked by rules you wrote.