Locate the source of truth
artifacts/api-server/src/mcp/catalogue.ts: core modules and atomic operations.extended-catalogue.ts,field-tools.ts,file-tools.ts: additional business tools.tool-schema.ts: UUID/date/money/file validators and editable-field allowlists.routes.ts: transport, tool registration, exact approvals, resources and prompts.bridge.ts,guards.ts: real-user delegation and referenced-record tenant checks.security-policy.ts,security-runtime.ts,security-scope.ts,security-store.ts: permissions, masking, safe scopes and persistent enforcement.outcome-catalogue.ts,outcome-server.ts,outcome-data.ts,detail-data.ts: higher-level read workflows and view data.lib/mcp-app-ui: shared host-rendered UI.lib/api-spec/openapi.yaml: session-management API contracts.
Add an atomic tool
- Reuse an existing authorized business API, or implement/test that API first. Never expose arbitrary HTTP/SQL, integration credentials, identity management, platform administration or payment execution.
- Add one focused catalogue operation with name, outcome-oriented description, module, method, internal path, sensitivity and a strict Zod input schema.
- Allow only editable business fields. Exclude tenant/user ownership, payment state, approval overrides, audit fields and internal flags. Preserve decimal-string money and ISO date validation.
- Add tenant checks for every referenced UUID. Reject foreign references before creating an approval, not just during execution.
- Check
actionOf: name/method determine action policy. A new POST command is not necessarily a create. Set sensitivity deliberately; do not rely on tool annotations for human approval. - If the tool must support narrowed record scopes, implement a safe scope relationship/filter. Unsupported scope relationships must deny; do not return globally authorized but connection-excluded records.
- Execute through the existing bridge and
runOperation, never by directly bypassing the business API from a tool callback. This preserves current user checks, quotas, scopes, response limits and audit. - Test allowed, denied, foreign-tenant, invalid-input, changed-role, revoked-token, default-approval and configurable-approval paths. Add output masking/size/document tests where applicable.
Descriptions should name the user's outcome, required UUIDs, relevant boundaries and meaningful uncertainty. Do not embed user data in descriptions or suggest that a reported risk certifies readiness. A tool-level sensitive flag is a default; current policy determines whether MCP review is required.
Add a read-only outcome or dashboard
Define module requirements and a strict input schema in the outcome catalogue. Compose existing authorized reads through injected execute, not raw database reads that omit connection scopes. Use before/finish security hooks. Limit scans, disclose incompleteness and keep unknown financial facts unknown.
Register shared UI metadata through _meta.ui.resourceUri; serve a self-contained resource with the standard MCP Apps MIME type. Use the existing App bridge for refresh, drill-down and theme/display capabilities. Do not fetch the API directly from the iframe or put bearer/session credentials inside it.
Native views must remain read-only. Human approval belongs in the application, not in a synthetic assistant response or a dashboard button. Validate record text as untrusted; do not let it choose executable tools or unchecked navigation destinations. Preserve structured/text fallback for non-UI hosts.
Optional provider-specific enhancements must be capability-detected. Do not require a provider model SDK to implement MCP or claim that widget support guarantees directory recommendations.
Contracts and schema changes
When adding/changing a session-management API, update lib/api-spec/openapi.yaml, regenerate with pnpm --filter @workspace/api-spec run codegen, then typecheck affected packages. Public machine-readable policy schemas come directly from the enforced validators.
Add database structures to the Drizzle schema and use the documented development-side migration workflow in replit.md. Only explicitly configured development startup may apply SQL migrations. Production and publish-test startup perform read-only assertions; Publish owns the development-to-production schema diff. Do not add build/startup production DDL or manually mark migrations applied to suppress a failure.
Documentation and publication
Update relevant guides in docs/mcp and provider guidance if behavior changed. These files are copied into the API build and served from an allowlisted public documentation registry; there is no separately edited HTML copy.
Adding a guide requires a registry entry in developer-docs.ts. Add public-route and link checks before release. Avoid fixed tool-count claims: the runtime catalogue is authoritative.
Download this guide as Markdown.