# ONE > ONE is GeoTech's Firebase-hosted internal operational workspace. It exposes a public HTTP API reference and a local MCP server for approved agents with a valid ONE API key or Firebase token. Codex plugin guide: https://one.geotech.one/docs/codex-plugin/ Remote OAuth MCP: https://one.geotech.one/api/mcp ## Public Docs - Human docs: https://one.geotech.one/docs/api - OpenAPI: https://one.geotech.one/openapi/geocrm.json - MCP manifest: https://one.geotech.one/mcp/geocrm.json - App: https://one.geotech.one - Branding: https://one.geotech.one/branding - Windows installer: https://one.geotech.one/install.ps1 - Windows uninstaller: https://one.geotech.one/uninstall.ps1 ## OneClient Windows Commands Install or repair the centrally distributed Windows client. This requests one UAC approval when needed: ```powershell irm https://one.geotech.one/install.ps1 | iex ``` Remove the local Windows service, tray, binaries, updater data, and config. Remove the retained offline inventory card separately in the authenticated ONE UI: ```powershell irm https://one.geotech.one/uninstall.ps1 | iex ``` ## HTTP API Base URL: https://one.geotech.one/api Availability: API-key mode requires the Firebase Function behind /api/**. If GET /health returns 404, use direct Firebase MCP mode with a short-lived Firebase ID token until the function is deployed. Authentication: - Authorization: Bearer - X-GeoCRM-Key: Core endpoints: - GET /health - GET /info (canonical app URLs and docs links; public) - GET /branding (authoritative GeoTech logos, exact palette, typography, patterns, four-page digital design system, all 89 design variables, resources, and agent usage rules; public) - GET /machines/client/latest (signed OneClient release manifest; public) - GET /machines/client/releases/{version}/{platform}/{arch}/{fileName} (OneClient release artifact; public) - PATCH /machines/{machineId}/color (set the global machine/calendar color; Firebase ID token and admin access required) - DELETE /machines/{machineId} (archive a remote machine; Firebase ID token and admin access required) - GET /me - GET /logs (seven-day diagnostic history; filter by from, to, level, category, connector, source, q, limit) - POST /logs (write a short-lived diagnostic log; requires write scope) - GET /boards - GET /boards/{boardId} - DELETE /boards/{boardId} (remove a non-protected board from the active workspace) - POST /boards/{boardId}/columns - DELETE /boards/{boardId}/columns/{columnId} (archive a non-core column while preserving item cell data) - GET /boards/{boardId}/items - POST /boards/{boardId}/items - GET /boards/{boardId}/items/duplicates - GET /boards/{boardId}/items/{itemId} - GET /search?q=... (searches all boards by default; optional board_id scopes to one board) - POST /contacts (create/update a contact and link an existing or newly created company) - GET /contacts/duplicates - POST /boards/{boardId}/items/move (move filtered items to another group; supports dry_run) - PATCH /boards/{boardId}/items/{itemId} - DELETE /boards/{boardId}/items/{itemId} - POST /boards/{boardId}/items/duplicates/merge - POST /boards/{boardId}/items/{itemId}/files - POST /boards/{boardId}/items/{itemId}/updates - POST /contacts/duplicates/merge - POST /task-automation/assign (Firebase-authenticated browser assignment or @Codex mention; assigns the task to the Codex agent for manual MCP pickup, or unassigns it) - POST /backups (queue a compact or full background backup; backups:write or Firebase owner auth) - GET /backups/jobs/{jobId} (poll status and completed backup metadata; backups:read or Firebase owner auth) - GET /documents/sign-requests (list private e-signature agreements; documents:read or Firebase Documents user) - POST /documents/sign-requests (raw PDF/image upload with X-File-Name, X-Document-Name, X-Signers, X-Subject, X-Message, and X-Settings; documents:write) - GET|PUT /documents/sign-requests/{requestId} (read or update a draft's recipients, actions, routing, message, reminders, and expiration) - POST /documents/sign-requests/{requestId}/documents (add a raw PDF/image document to a draft; 10 documents maximum) - PUT /documents/sign-requests/{requestId}/prepare (place signature, initials, text, name, email, title, date-signed, and checkbox fields) - POST /documents/sign-requests/{requestId}/send (send private links in parallel or configured routing order; documents:send) - GET /documents/sign-templates and POST /documents/sign-requests/from-template (list and use reusable agreements) - POST /documents/sign-requests/{requestId}/template (save a prepared draft as a reusable template) Assigning Codex sets the virtual Codex assignee and a queued marker on the task. No worker job is created; a human copies the shareable task link and hands it to Codex manually. - GET /task-projects/boards (least-privilege project-task board discovery; tasks:read) - GET /task-projects/boards/{boardId}/projects (least-privilege project summary discovery; tasks:read) - GET /task-projects/boards/{boardId}/projects/{projectId} (one safe project summary; tasks:read) - GET /boards/{boardId}/projects/{projectId}/tasks (list/search tasks, including exact slackUrl; tasks:read) - POST /boards/{boardId}/projects/{projectId}/tasks (batch task and one-level subtask creation; tasks:write) - GET /boards/{boardId}/projects/{projectId}/tasks/{taskId} (complete developer-task context; tasks:read) - PATCH /boards/{boardId}/projects/{projectId}/tasks/{taskId} (revision-safe task update; tasks:write) - GET/PATCH /boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId} (full subtask context/update) - GET /boards/{boardId}/projects/{projectId}/tasks/{taskId}/images/{assetId} (authenticated task image; tasks:read) - POST /boards/{boardId}/projects/{projectId}/tasks/{taskId}/comments (Codex task comment; tasks:comment) - PATCH /boards/{boardId}/projects/{projectId}/tasks/{taskId}/review-state (In Progress or Review only; tasks:review) - POST /finance/forecast/view (deterministic 13-week or 12-month cash outlook with Base/Upside/Downside scenarios, liquid or treasury scope, dated account-balance anchoring, distinct outstanding Accounts Receivable payment drivers, approved Accounts Payable committed outflows, approval-pending A/P exposure that remains excluded from cash until approved, scope-boundary cash movement, 12 monthly manual-verification buckets, historical FX provenance, and quality warnings; finance:read, read, write, or Firebase Finance user auth) - POST /finance/forecast/events (create an idempotent one-off or recurring cash plan; finance:write, write, or Firebase Finance user auth; requires X-Idempotency-Key) - PATCH /finance/forecast/events/{eventId} (edit, archive, or restore a plan with expectedUpdatedAt optimistic concurrency; finance:write, write, or Firebase Finance user auth) - PUT /finance/forecast/settings (update the minimum-cash threshold and default scope/horizon with optimistic concurrency; finance:write, write, or Firebase Finance user auth) - POST /finance/view (bounded Finance transaction matching; finance:read or Firebase Finance user auth) - POST /finance/balance-screenshots (raw transient ING account, ING credit-card, or Wise screenshot; Gemini recognition plus deterministic known-account matching adds dated balances; ING investment Belegd/Gelddeel values persist as invested/available-cash components and only available cash enters cash forecasts; credit cards use Current balance only, including zero, and normalize displayed debt as negative; finance:write, write, or Firebase Finance user auth; optional X-Balance-Date; raw image is never stored) - GET|POST /finance/bills (list or create Accounts Payable bills; writes require a stable X-Idempotency-Key) - GET /finance/bills/aging, DELETE /finance/bills/{billId}, and POST /finance/bills/{billId}/approve|unapprove|reject|cancel|match|unmatch (AP aging, guarded deletion of uncommitted rows with source scans preserved, approval, and outgoing-bank matching; finance:read/finance:write or Firebase Finance user auth) - POST /finance/bills/bulk-approve and POST /finance/bills/rematch (bounded approval and bank reconciliation batches; finance:write or write scope) - GET|POST /finance/invoices (list or create Accounts Receivable invoice drafts; writes require a stable X-Idempotency-Key) - POST /finance/invoices/import (Gemini extraction from a raw PDF/image into a review-required AR draft; duplicate source files reuse their existing draft) - GET /finance/invoice-customers and GET /finance/accounts (Companies customer picker and invoice-ready Finance payment accounts) - PATCH /finance/accounts/{accountId}/payment-details (owner-only BIC/SWIFT, IBAN, or account-number maintenance) - GET /finance/invoices/aging and POST /finance/invoices/{invoiceId}/issue|revise|void|match|unmatch (AR aging, immutable sequential issue, safe unsent revision/void, and guarded incoming-bank matching) - GET /finance/invoices/{invoiceId}/preview (authenticated non-numbered draft preview or inline current immutable PDF) - GET /finance/invoices/{invoiceId}/pdf (authenticated immutable issued-invoice PDF download) - POST /finance/invoices/{invoiceId}/send (Gmail delivery with PDF attachment and delivery audit; finance:invoices:send or write scope) - GET|PATCH /finance/invoice-settings (read issuer/payment/numbering configuration; updates are owner-only and issuer VAT is optional) - POST /finance/exports/journal.csv (bounded canonical journal CSV with formula-injection protection; finance:read, read, write, or Firebase Finance user auth) - GET /finance/exports/drive/accounts and POST /finance/drive/authorization (session-locked Drive readiness plus in-context Google authorization; the server exchanges the one-time code, requires the Google email to equal the Firebase session email, stores a dedicated per-user refresh token, and never returns tokens to the browser; API keys are rejected) - POST /finance/drive/browser, POST /finance/drive/destination/verify, and POST /finance/drive/destination/create (server-side My Drive/Shared Drive folder browsing and idempotent creation of one new app-owned destination folder; requires drive.file plus drive.readonly and explicit canAddChildren before and after creation; API keys are rejected) - GET|POST /finance/exports/drive and GET /finance/exports/drive/{exportId} (Finance-protected monthly immutable Google Drive/Shared Drive export history, queued background creation, and status polling; POST returns 202 immediately, creates only ONE-owned folders/files, and never changes old Drive content; Firebase Finance editor/owner required for creation) - MCP finance_list_drive_accounts, finance_list_drive_exports, finance_get_drive_export, and finance_create_drive_export (OAuth-scoped account readiness, queueing, and polling for the same durable Drive export workflow; creation requires crm.write and returns before the background copy finishes) - GET /finance/transactions/{transactionId}/evidence (list private receipt/invoice metadata; finance:evidence:read or Firebase Finance user auth) - POST /finance/transactions/{transactionId}/evidence (raw validated PDF/image upload, 20 MB max; finance:evidence:write or Firebase Finance user auth; use X-File-Name, X-Evidence-Type, and stable X-Idempotency-Key headers) - GET /finance/transactions/{transactionId}/evidence/{evidenceId} (authenticated private preview/download; finance:evidence:read or Firebase Finance user auth) - DELETE /finance/transactions/{transactionId}/evidence/{evidenceId} (delete one evidence file only; finance:evidence:write or Firebase Finance user auth) - POST /finance/categorization/context (bounded approved-decision retrieval; finance:read) - POST /finance/categorization/vector-memory/stats (active embedding namespace counters; finance:read or Firebase Finance user auth) - POST /finance/categorization/vector-memory/sync (embed selected human-approved decisions or a YYYY-MM page with finance:suggest; pass `replaceExisting: true` with one transaction ID and finance:apply to remove its prior decision vector/link and generate a fresh replacement; Firebase Finance user auth is also supported) - POST /finance/categorization/vector-memory/clear (explicitly confirmed embedding-only reset; finance:apply or Firebase owner auth) - POST /finance/categorization/runs (start an audited GPT-5.6 Sol, GPT-5.6 Terra, or OpenRouter Kimi K3 run; finance:suggest) - POST /finance/categorization/suggestions (validate votes and, unless dry-run, save AI-provenance category decisions; finance:suggest) - POST /finance/categorization/retrieve (deterministically match uncategorized transactions against approved Finance vector memory; no categorization LLM call; Firebase user auth; legacy `/run-ai` alias remains accepted) - POST /finance/categorization/transactions/{transactionId}/review (mark an AI result correct/incorrect; Exclude from AI removes that transaction's vector memory and re-inclusion queues a fresh eligible replacement; finance:apply) - GET /me/work (personal-key or Firebase-user My Work dashboard) - GET/PUT/DELETE /me/focus (validated personal current tasks, one per project; DELETE can clear one project) - GET /team-focus?boardId={boardId}&projectId={projectId} (visible validated focus records) - GET/POST /me/agent-keys and DELETE /me/agent-keys/{keyId} (Firebase-authenticated self-service personal keys) - PATCH /boards/{boardId}/projects/{projectId}/source-control (project-editor single repository or Perforce configuration; no credentials) - POST /webhooks/github (signed GitHub push and pull-request metadata) - POST /source-events/perforce (service-authenticated sanitized changelist metadata) - GET/POST /slack/task-automation/channels/{teamId}/{channelId} (channel-to-project mapping) - GET/POST /slack/task-automation/proposals (list/create summary-only previews) - PATCH /slack/task-automation/proposals/{proposalId} (refresh a pending preview) - POST /slack/task-automation/proposals/{proposalId}/approve (apply an exact participant-approved preview) ## MCP Branding workflow: before creating or substantially revising a presentation, Complex Decision, product or website design, UI, document, report, chart, diagram, campaign, email, social post, or other visual GeoTech work, call `get_brand_standards`. Treat its approved artwork, exact values, Cover, Getting Started, Foundations, and Tokens guidance, complete Brand/Color/Scale/Typography variables, guardrails, clear-space, and contrast rules as authoritative; use only the returned ONE/Firebase-hosted asset URLs and never substitute external file links; never redraw or transform the mark. Backup workflow: create a `Backups / Codex` API key, call `create_backup` with compact or full mode, and let the tool poll the background Firebase job. Use `get_backup_job` only when a prior call returned before completion. Brain Dump workflow: create a `Brain Dump only` API key, use `GEOCRM_MCP_PROFILE=brain_dump`, call `get_brain_dump_context` before ideating, then save one or more generated results with `add_brain_dump_ideas`. The key is board-scoped and should never be copied into prompts, logs, or board fields. Documents workflow: create a `Documents / e-signature` API key, use the full MCP profile, then use `create_signature_request` or `create_signature_request_from_template`, `prepare_signature_request`, review with `get_signature_request`, and finally `send_signature_request`. The list/get/template/void tools provide lifecycle control without exposing private signing tokens. Remote BackOffice workflow: the OAuth MCP exposes read-only tools for Finance Overview, Flow, Accounts, Transactions, and Imports; Documents agreements and templates; Hardware inventory; and Procurement requests. Every call rechecks the signed-in user's current module grant, and Procurement also rechecks request-level visibility. Complex Decisions workflow: use `upload_complex_decision` through the OAuth Codex plugin while signed in as the ONE owner, or call `POST /complex-decisions` with a personal owner API key. Every upload is forced to owner-only visibility, active HTML is sanitized, and previous per-report grants are removed. Finance forecast workflow: use the full MCP profile with a Finance-capable key. Start with `finance_get_cash_forecast`, then add retry-safe planned movement with `finance_create_cash_plan`; use the returned `updatedAt` value for update, archive, and restore operations. Forecast values are deterministic calculations from classified cash history and plans—no LLM generates financial amounts. Finance account screenshot workflow: use the full MCP profile with a Finance write-capable key and call `upload_account_balance_screenshot` with a local ING or Wise image. Gemini reads only the direct provider screen; known account matching and balance writes are deterministic. ING investment Belegd/Gelddeel values stay together as invested and available-cash components, with only available cash entering the cash forecast. Converted aggregate totals and ambiguous rows are skipped, and the raw screenshot is never stored. Slack project-task workflow: mention ONE in a channel thread and ask naturally to turn the conversation into project tasks or refresh tasks already linked to it. The bot reads the complete live thread, persists a summary-only 24-hour preview, refreshes after replies, and applies only after a thread participant approves the latest snapshot with `white_check_mark`. Store Slack permalinks on tasks, append details/comments, and preserve later human edits. Local command: ```json { "mcpServers": { "one": { "command": "node", "args": ["C:\\Projects\\GeoCRM\\mcp\\geocrm-mcp.mjs"], "env": { "GEOCRM_AUTH_MODE": "api", "GEOCRM_MCP_PROFILE": "tasks", "GEOCRM_API_BASE_URL": "https://one.geotech.one/api", "GEOCRM_API_KEY": "" } } } } ``` Tools: - geocrm_health - get_app_info - get_brand_standards - list_logs - write_log - list_boards - get_board - upload_complex_decision - delete_board - list_board_items - search_items - find_board_item_duplicates - find_contact_duplicates - upsert_contact - list_signature_requests - get_signature_request - list_signature_templates - list_hardware_inventory - get_hardware_asset - list_procurement_requests - get_procurement_request - create_signature_request - create_signature_request_from_template - prepare_signature_request - save_signature_template - send_signature_request - void_signature_request - get_item - ensure_board_column - create_item - update_item - move_board_items - delete_item - set_item_file_field - add_item_update - merge_board_item_duplicates - merge_contact_duplicates - get_task_context - get_task_image (pass subtask_id for an image returned under a subtask) - add_task_comment - set_task_review_state - finance_get_overview - finance_list_accounts - finance_list_transactions - finance_list_imports - finance_list_invoices - finance_get_invoice - finance_create_invoice - finance_import_invoice (local stdio only; reads the supplied local PDF/image path) - finance_get_cash_forecast - finance_create_cash_plan - finance_update_cash_plan - finance_archive_cash_plan - finance_update_cash_forecast_settings - upload_account_balance_screenshot Developer-task workflow: create a self-service personal agent key from My Work or a project board, run the local stdio MCP server with `GEOCRM_MCP_PROFILE=tasks`, call `get_my_work` or `get_task_context` first, inspect every returned image with `get_task_image`, and reload context before each feedback iteration. The task/focus tools are not advertised by the remote OAuth MCP transport. Personal keys may create tasks and edit only tasks assigned to their owner. After verified work, add one concise result comment and set the task to Review. Agents must never mark the task Done; a human reviewer owns completion. Work-link automation: projects store non-secret GitHub repository or Perforce depot mappings. Signed GitHub webhooks and an approved Perforce synchronization service send metadata only. Exact task URLs and GCRM keys attach immediately; policy matches at or above 0.90 with a 0.15 lead attach automatically; 0.65-0.89 or ambiguous matches become one-click suggestions. Source events never change workflow status. The bridge claims debounced enrichment jobs, and AI updates only empty or still-AI-managed fields with provenance and Undo. ## Log History Use https://one.geotech.one/api/logs for recent diagnostic history. Logs are retained for seven days and are categorized as app, llm, connector, or system with level, connector, source, timestamp, message, and optional details. Useful filters: category=llm,connector; connector=slack,gmail,openrouter,codex; level=warn,error; source=web,bridge,mcp,geoCrmApi; from/to ISO timestamps; q=text search; limit up to 500. Agents should read logs before guessing at bridge, connector, LLM, or app failures. Agents may write concise factual diagnostics through POST /logs or the write_log MCP tool, but must never log secrets, API keys, Firebase ID tokens, OAuth tokens, session cookies, or private credential material. ## Slack Bot The Slack Codex bot is chat-only. Users should DM the app or mention it in natural language; do not require slash commands, command keywords, shell commands, or extra command syntax. For clear ONE requests, resolve intent from chat and call ONE API or MCP tools internally to add, delete, edit, remove, search, or update board entities. For questions like "what is the ONE website", "what is the ONE login URL", or "where is the ONE web page", answer directly from app metadata: the primary ONE website and login page is https://one.geotech.one/ and the Firebase Hosting fallback is https://geotech-crm.web.app. ONE was formerly called GeoCRM, so legacy technical identifiers may still use that name. Use GET /api/info or the get_app_info MCP tool for canonical app URLs, API docs, OpenAPI, and MCP manifest links. For lookup requests, search all ONE boards by default unless the user explicitly names a board. Use concise entity queries and allow flexible token/prefix matching, such as `chris stone` matching `Christopher Stone`. For bridge execution, prefer `npm run bridge` on the remote bridge host. The bridge supervises the Slack bot, reuses the bridge token, exposes status/log controls to the hosted drawer, and restarts the bot when it exits while enabled. ## Connector Summaries Contact connector summaries should aggregate every available connector for the selected contact and date range. Save one latest summary update per connector source. For substantive Gmail, Slack, or future connector results, write a 100 to 250 word plain-language business summary only; do not save raw message dumps, full email bodies, recipient lists, email addresses, mailto links, URLs, social links, source links, search queries, message IDs, quoted headers, or signatures. ## Next Meeting Contacts include a Calendar-backed `Next meeting` special column. The header update action reads future Google Calendar events for selected rows through the Codex bridge, writes `meetingCount | DD.MM.YYYY` or `0 | No future meeting` to the stored `Next meeting` field, and renders the cell with a green-to-red urgency badge based on how close the meeting date is. ## Security Do not store live ONE API keys in public documentation, source control, issue trackers, logs, screenshots, or agent thread records. Use placeholders in examples and keep secrets in approved local client configuration, a password manager, or a platform secret store.