get_project_context
Get a redacted project snapshot: secrets metadata, environment, declared providers, hooks, and audit activity. Use as the first call to orient an AI agent without exposing plaintext secret values.
Instructions
[agent] Return a single redacted snapshot of everything an AI agent typically wants to know about this project: secrets present (keys + metadata only), detected env, manifest declarations, configured providers, registered hooks, and recent audit activity. Use this as the very first call in a session to orient the agent before it asks for any individual secret; prefer list_secrets for a flat key listing, check_project for manifest-vs-keyring drift, and audit_log for a deeper access trail. Read-only and value-safe — no plaintext secret values are ever included. Returns a single pretty-printed JSON document; shape is intentionally broad and may grow over time, so read defensively.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | Where the secret lives. 'global' = user keyring (default if omitted on reads), 'project' = scoped to projectPath, 'team' = team-shared (needs teamId), 'org' = org-shared (needs orgId). | |
| projectPath | No | Absolute path to the project root for project-scoped secrets and policy resolution. Defaults to the MCP server's current working directory when omitted. | |
| teamId | No | Team identifier for team-scoped secrets. Required only when scope='team'. Example: 'acme-platform'. | |
| orgId | No | Organization identifier for org-scoped secrets. Required only when scope='org'. Example: 'acme-corp'. |
Implementation Reference
- src/core/context.ts:59-134 (handler)Core handler function that builds the ProjectContext object: collects secrets (redacted), manifest info, environment detection, providers, hooks, and recent audit activity. This is the actual business logic executed when 'get_project_context' is called.
export function getProjectContext(opts: KeyringOptions = {}): ProjectContext { const projectPath = opts.projectPath ?? process.cwd(); const envResult = collapseEnvironment({ projectPath }); const secretsList = listSecrets({ ...opts, projectPath, silent: true, }); let expiredCount = 0; let staleCount = 0; let protectedCount = 0; const secrets: SecretSummary[] = secretsList.map((entry) => { const meta = entry.envelope?.meta; const decay = entry.decay; if (decay?.isExpired) expiredCount++; if (decay?.isStale) staleCount++; if (meta?.requiresApproval) protectedCount++; return { key: entry.key, scope: entry.scope, tags: meta?.tags, description: meta?.description, provider: meta?.provider, requiresApproval: meta?.requiresApproval, jitProvider: meta?.jitProvider, hasStates: !!(entry.envelope?.states && Object.keys(entry.envelope.states).length > 0), isExpired: decay?.isExpired ?? false, isStale: decay?.isStale ?? false, timeRemaining: decay?.timeRemaining ?? null, accessCount: meta?.accessCount ?? 0, lastAccessed: meta?.lastAccessedAt ?? null, rotationFormat: meta?.rotationFormat, }; }); // Manifest analysis let manifest: ProjectContext["manifest"] = null; const config = readProjectConfig(projectPath); if (config?.secrets) { const declaredKeys = Object.keys(config.secrets); const existingKeys = new Set(secrets.map((s) => s.key)); const missing = declaredKeys.filter((k) => !existingKeys.has(k)); manifest = { declared: declaredKeys.length, missing }; } // Recent audit activity (last 20 events, redacted) const recentEvents = queryAudit({ limit: 20 }); const recentActions = recentEvents.map((e) => ({ action: e.action, key: e.key, source: e.source, timestamp: e.timestamp, })); return { projectPath, environment: envResult ? { env: envResult.env, source: envResult.source } : null, secrets, totalSecrets: secrets.length, expiredCount, staleCount, protectedCount, manifest, validationProviders: providerRegistry.listProviders().map((p) => p.name), jitProviders: jitRegistry.listProviders().map((p) => p.name), hooksCount: listHooks().length, recentActions, }; } - src/core/context.ts:16-57 (schema)Type definitions for SecretSummary and ProjectContext interfaces that define the shape of the return value of get_project_context.
export interface SecretSummary { key: string; scope: string; tags?: string[]; description?: string; provider?: string; requiresApproval?: boolean; jitProvider?: string; hasStates: boolean; isExpired: boolean; isStale: boolean; timeRemaining: string | null; accessCount: number; lastAccessed: string | null; rotationFormat?: string; } export interface ProjectContext { projectPath: string; environment: { env: string; source: string; } | null; secrets: SecretSummary[]; totalSecrets: number; expiredCount: number; staleCount: number; protectedCount: number; manifest: { declared: number; missing: string[]; } | null; validationProviders: string[]; jitProviders: string[]; hooksCount: number; recentActions: Array<{ action: string; key?: string; source: string; timestamp: string; }>; } - src/mcp/tools/project.ts:187-210 (handler)MCP tool handler registration for 'get_project_context'. This is the entry point that receives MCP params, enforces policy, calls getProjectContext(), and returns the result as JSON text.
server.tool( "get_project_context", [ "[agent] Return a single redacted snapshot of everything an AI agent typically wants to know about this project: secrets present (keys + metadata only), detected env, manifest declarations, configured providers, registered hooks, and recent audit activity.", "Use this as the very first call in a session to orient the agent before it asks for any individual secret; prefer `list_secrets` for a flat key listing, `check_project` for manifest-vs-keyring drift, and `audit_log` for a deeper access trail.", "Read-only and value-safe — no plaintext secret values are ever included. Returns a single pretty-printed JSON document; shape is intentionally broad and may grow over time, so read defensively.", ].join(" "), { scope, projectPath, teamId, orgId, }, async (params) => { const toolBlock = enforceToolPolicy( "get_project_context", params.projectPath, ); if (toolBlock) return toolBlock; const context = getProjectContext(opts(params)); return text(JSON.stringify(context, null, 2)); }, ); - src/mcp/tool-registration.ts:19-30 (registration)Registration of all MCP tools on the server. registerProjectTools (which registers 'get_project_context') is called on line 21.
export function registerMcpTools(server: McpServer): void { registerSecretTools(server); registerProjectTools(server); registerTunnelTools(server); registerTeleportTools(server); registerAuditTools(server); registerValidationTools(server); registerHookTools(server); registerToolingTools(server); registerAgentTools(server); registerPolicyTools(server); } - src/mcp/tools/_shared.ts:18-33 (helper)Helper function 'opts()' that converts MCP tool params into KeyringOptions, used by the get_project_context handler to pass options to getProjectContext().
export function opts(params: { scope?: string; projectPath?: string; env?: string; teamId?: string; orgId?: string; }): KeyringOptions { return { scope: params.scope as Scope | undefined, projectPath: params.projectPath ?? process.cwd(), teamId: params.teamId, orgId: params.orgId, env: params.env, source: "mcp", }; }