Skip to content

Dev#694

Merged
ashwin31 merged 2 commits into
masterfrom
dev
Jun 1, 2026
Merged

Dev#694
ashwin31 merged 2 commits into
masterfrom
dev

Conversation

@ashwin31

@ashwin31 ashwin31 commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

Release Notes

  • New Features

    • Personal Access Tokens (PATs) for programmatic API access with optional expiration dates.
    • New "API Tokens" settings page for creating, managing, and revoking tokens.
    • Token-based authentication for external integrations.
    • BottleCRM MCP Server for Claude Desktop integration via stdio protocol.
    • Support for token-scoped API access with full org/profile isolation.
  • Documentation

    • MCP Server design document and phase 1 implementation guide.
    • Server setup and configuration documentation.

ashwin31 added 2 commits June 1, 2026 18:45
…nd initialize a new MCP server for AI agent integrations.
Copilot AI review requested due to automatic review settings June 1, 2026 14:31
} catch (err) {
console.error('Failed to load API tokens:', err);
return { tokens: [], loadError: err?.message || 'Failed to load tokens' };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrecoverable syntax error. (20% scanned).

return { tokens: data.tokens || [] };
} catch (err) {
console.error('Failed to load API tokens:', err);
return { tokens: [], loadError: err?.message || 'Failed to load tokens' };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expected ':' and instead saw 'message'.
Expected '}' to match '{' from line 11 and instead saw 'Failed to load tokens'.
Expected an identifier and instead saw '.'.
Expected an identifier and instead saw '||'.
Missing semicolon.
Unnecessary semicolon.

/** @type {import('./$types').PageServerLoad} */
export async function load({ cookies, locals }) {
try {
const data = await apiRequest('/profile/tokens/', {}, { cookies, org: locals?.org });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
'object short notation' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
Expected ')' and instead saw ';'.
Expected ':' and instead saw 'org'.
Expected '}' to match '{' from line 7 and instead saw ')'.
Expected an identifier and instead saw '.'.
Expected an identifier and instead saw '}'.
Missing semicolon.

import { apiRequest } from '$lib/api-helpers.js';

/** @type {import('./$types').PageServerLoad} */
export async function load({ cookies, locals }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'destructuring binding' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
'export' is only available in ES6 (use 'esversion: 6').
Expected an assignment or function call and instead saw an expression.
Missing semicolon.
Unexpected 'async'.

@@ -0,0 +1,57 @@
import { fail } from '@sveltejs/kit';
import { apiRequest } from '$lib/api-helpers.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'import' is only available in ES6 (use 'esversion: 6').

@@ -0,0 +1,57 @@
import { fail } from '@sveltejs/kit';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'import' is only available in ES6 (use 'esversion: 6').

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0d02bd02-442f-49e9-aef9-fc520d1da202

📥 Commits

Reviewing files that changed from the base of the PR and between 5f3bf75 and dbde120.

⛔ Files ignored due to path filters (1)
  • mcp_server/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • backend/common/middleware/get_company.py
  • backend/common/migrations/0027_personalaccesstoken.py
  • backend/common/models.py
  • backend/common/pat_auth.py
  • backend/common/rls/__init__.py
  • backend/common/serializer.py
  • backend/common/tests/test_pat_api.py
  • backend/common/tests/test_pat_auth.py
  • backend/common/tests/test_pat_integration.py
  • backend/common/tests/test_pat_model.py
  • backend/common/urls.py
  • backend/common/views/pat_views.py
  • backend/crm/settings.py
  • docs/plans/2026-06-01-mcp-server-design.md
  • docs/plans/2026-06-01-mcp-server-phase1.md
  • frontend/src/lib/components/layout/AppSidebar.svelte
  • frontend/src/routes/(app)/settings/api-tokens/+page.server.js
  • frontend/src/routes/(app)/settings/api-tokens/+page.svelte
  • mcp_server/README.md
  • mcp_server/pyproject.toml
  • mcp_server/src/bcrm_mcp/__init__.py
  • mcp_server/src/bcrm_mcp/client.py
  • mcp_server/src/bcrm_mcp/config.py
  • mcp_server/src/bcrm_mcp/entities.py
  • mcp_server/src/bcrm_mcp/server.py
  • mcp_server/src/bcrm_mcp/tools.py
  • mcp_server/tests/__init__.py
  • mcp_server/tests/test_client.py
  • mcp_server/tests/test_entities.py
  • mcp_server/tests/test_server_registration.py
  • mcp_server/tests/test_tools.py

📝 Walkthrough

Walkthrough

This PR implements a comprehensive Personal Access Token (PAT) authentication system enabling programmatic access to BottleCRM via an MCP (Model Context Protocol) server. The backend adds token model, validation, and API endpoints; the frontend provides token management UI; and a standalone Python MCP server acts as a thin HTTP client with generic CRUD/action tools.

Changes

Personal Access Token System (Backend + Frontend + MCP)

Layer / File(s) Summary
Token Model and Generation
backend/common/models.py, backend/common/migrations/0027_personalaccesstoken.py
PersonalAccessToken Django model with SHA-256 hashing, raw token generation via secrets, validity checking (revocation/expiry), and migration defining UUID primary key, token_hash uniqueness, org/profile ownership, and audit timestamps.
PAT Authentication and Validation
backend/common/pat_auth.py
New pat_auth module extracting tokens from Bearer/Token headers, resolving by hash, validating active/non-revoked/non-expired state, and rejecting tokens with inactive profile/org; DRF authentication class populating request context and throttling last_used_at updates; OpenAPI security definition for bearer scheme.
Middleware PAT Resolution
backend/common/middleware/get_company.py
GetProfileAndOrg middleware integration extracting and resolving PATs early in request pipeline before JWT processing, setting org/profile context on request, and storing resolved tokens for DRF reuse; swallows AuthenticationFailed to let downstream middleware return 403.
API Serializers and Views
backend/common/serializer.py, backend/common/views/pat_views.py, backend/common/urls.py
Serializers for read-only token listing (hiding token_hash) and creation (with name/scopes/expires_at validation); views implementing org/profile-scoped list/create and revoke endpoints with IDOR protection; URL routes for /api/profile/tokens/ collection and detail endpoints.
DRF Authentication Configuration
backend/crm/settings.py
Updated REST_FRAMEWORK DEFAULT_AUTHENTICATION_CLASSES to include PATAuthentication before JWT, enabling PAT authentication in DRF views.
Backend Test Coverage
backend/common/tests/test_pat_model.py, test_pat_auth.py, test_pat_api.py, test_pat_integration.py
Model tests for token generation/hashing and validity transitions; auth tests for header extraction and validation across variants; API tests for CRUD/authorization/field injection prevention/IDOR; full middleware+auth stack integration tests; cross-org isolation regression test; RLS policy validation.
Row-Level Security Policy Notes
backend/common/rls/__init__.py
Documentation clarifying personal_access_token is not RLS-protected; tenant isolation enforced via explicit org+profile filters in views.
Frontend Token Management UI
frontend/src/lib/components/layout/AppSidebar.svelte, frontend/src/routes/(app)/settings/api-tokens/+page.server.js, frontend/src/routes/(app)/settings/api-tokens/+page.svelte
SvelteKit settings page with token list, create form, copy-once token display, and revoke confirmation flow; server-side load function and form actions for API communication; sidebar navigation link to /settings/api-tokens with KeyRound icon.
MCP HTTP Client and Configuration
mcp_server/src/bcrm_mcp/client.py, mcp_server/src/bcrm_mcp/config.py
Async httpx-based CrmClient with bearer token authorization, error handling for 4xx/5xx with JSON/text fallback, and GET/POST/PATCH/DELETE convenience methods; Settings dataclass reading BCRM_BASE_URL and BCRM_TOKEN from environment with validation and normalization.
MCP Entity Registry and Path Resolution
mcp_server/src/bcrm_mcp/entities.py
Entity metadata mapping CRM entity names to API paths (e.g., leads → /api/leads/) and per-entity allowed actions; path resolution helper supporting list/detail path construction; CONFIRM_REQUIRED_ACTIONS set for safety gates.
MCP Generic CRUD and Action Tools
mcp_server/src/bcrm_mcp/tools.py
Async tool functions for entity search (with limit capping), get, create, update, delete (confirm-gated), and custom actions; OpenAPI-driven schema inspection extracting per-entity field metadata, required fields, and enum values with defensive component name matching.
MCP Tools Test Suite
mcp_server/tests/test_tools.py
Tests validating tool search limit enforcement, CRUD endpoint construction, delete/action confirmation requirements, entity/action validation, and OpenAPI schema field extraction for required and enum metadata.
MCP Server Scaffolding and Integration Tests
mcp_server/src/bcrm_mcp/__init__.py, mcp_server/src/bcrm_mcp/server.py, mcp_server/pyproject.toml, mcp_server/tests/test_client.py, mcp_server/tests/test_entities.py, mcp_server/tests/test_server_registration.py
FastMCP server factory registering CRUD/action/describe tools with read/write/destructive hints and lazy client initialization; pyproject.toml with dependencies, console script entry point, and test configuration; tests for HTTP client bearer auth and error handling, entity path resolution, and tool registration/hints.
Design and Implementation Documentation
docs/plans/2026-06-01-mcp-server-design.md, docs/plans/2026-06-01-mcp-server-phase1.md, mcp_server/README.md
High-level MCP architecture and auth flow design; detailed Phase 1 task breakdown for backend (model/auth/endpoints), frontend (UI), and MCP server (client/tools/scaffolding); MCP README with setup, token creation, Claude Desktop config, tool inventory, security model, smoke test, and development commands.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

A rabbit hops through tokens bright,
bcrm_pat_ dancing in the light,
From Django dreams to Claude's embrace,
PATs now guard this CRM space! 🐰✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ashwin31 ashwin31 merged commit e320dfc into master Jun 1, 2026
3 of 6 checks passed
@ashwin31 ashwin31 deleted the dev branch June 1, 2026 14:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants