Castan

Connect Castan to your assistant

Castan is a company memory for small companies and solo founders. It holds what a company knows across email, Slack, calendar, meetings, documents, code, customers and the books, and it answers questions about that material.

This page is the setup and usage guide for the Castan Model Context Protocol server, which opens that same memory to any MCP client. An assistant connected to it can ask what the company knows, see what is on the calendar, read recaps of recorded calls, list customers and open invoices, and check what the company is building. Every tool reads one workspace and no tool writes anything.

Create a keyStart free

The endpoint

Endpoint
https://castan.ai/api/mcp
Transport
Streamable HTTP, one POST per request
Session
None. The server is stateless, so every request stands on its own
Responses
Plain JSON. The server does not open an SSE stream
Authentication
Bearer API key, created by a workspace owner in the Castan app
Without a key
initialize, tools/list, ping and the initialized notification answer. Every tools/call does not
Server name and version
castan, version 1.0.0
Writes
None. Every tool is read only, and every tool says so in its annotations
Scope
One key opens exactly one workspace, and one role inside it
Server card
https://castan.ai/.well-known/mcp/server-card.json, no key needed

The endpoint answers POST. GET and DELETE are accepted by the route and answered by the transport, but there is nothing to fetch or delete on a stateless server, so a client only ever needs POST.

The handshake works without a key

A directory that lists MCP servers, or a person deciding whether to sign up at all, has to be able to see what the server offers before anybody hands it a credential. Four methods answer a caller with no key: initialize, notifications/initialized, ping and tools/list. Every tools/call needs a key, always, and so does anything outside that list.

See the whole tool catalogue with no account at all
curl -s https://castan.ai/api/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

What comes back has the server name, the server version and the tool catalogue in it, and nothing else. There is no workspace name, no plan, no role, no count, no connected source, and no answer to the question whether a given company has an account. The code that answers a keyless request never opens a database connection, so none of that is available to leak. A batch is judged whole: a JSON-RPC array that puts a tools/call beside a tools/list is refused entirely rather than partly answered.

The catalogue a keyless caller sees is the full one, all eight tools, including the two an owner key gets and a member key does not. The keyless path is rate limited to 60 requests an hour per calling address. A caller past it gets HTTP 429 with a Retry-After header. A key lifts that limit.

Getting a key

Castan uses its own bearer API key. There is no OAuth flow, and none is required by any of the clients below. A key looks like ck_ followed by 32 characters, and it goes on every request.

Authorization: Bearer ck_your_key_here
  1. Sign in to Castan as an owner of the workspace you want to read.
  2. Open Settings and go to the API and MCP tab. The whole tab is owner only, so a member account does not see it at all.
  3. Give the key a name, choose owner access or member access, and create it.
  4. Copy the key immediately. Castan stores only a SHA-256 hash of it, so the key itself is shown once and never again.

A key can be revoked in the same place at any time, and the list shows when each key was last used. A key belongs to the workspace it was created in. If an assistant is reading the wrong workspace, a new key will not fix that: sign in to the workspace you meant and create the key there.

What one key opens

One key opens exactly one workspace, with one role: owner or member. The role is fixed when the key is created and cannot be changed by the caller. A key is resolved to that workspace and that role before any tool code runs, every query then runs inside a transaction bound to the workspace, and row level security in the database sits behind the application as a second wall. There is no tool argument that names a workspace, so there is nothing for a caller to change, guess or traverse.

A member key never sees the money
  • It does not get the open_receivables or finance_summary tools at all. They are absent from the tool list, not present and refusing.
  • It gets no money columns from customers. Names and domains only.
  • It gets no invoice count from workspace.
  • It never sees Stripe, QuickBooks or any other finance source in the connected sources list.
  • It cannot retrieve invoice or payment text through ask_brain. The restriction is applied inside the search itself, both in the vector pass and the full text pass, so out of scope material is never read even briefly.

An owner key sees everything above.

Everything is read only

There is no tool that creates, edits, deletes, sends, schedules or pays anything. The server exposes eight tools and all eight are queries. Every one of them carries readOnlyHint: true and destructiveHint: false in its annotations, with openWorldHint decided per tool: false on the seven that read only what the workspace already holds, true on upcoming_meetings, the one tool whose answer is a window on a calendar that people outside Castan own and can change between two identical calls. A key is a read credential and nothing more. Connecting an assistant to Castan cannot change what Castan holds.

The eight tools

Arguments are validated before a tool runs. Every tool answers for the one workspace the key opens, and every answer names that workspace, so a client is never guessing which company it is reading. Answers come back as JSON inside a text content block.

  • workspaceWorkspace and what it holds

    The workspace name and plan, whether the key has owner or member access, every connected source with its status and last sync time, and counts of the people, companies, messages, meetings, documents, tasks and projects held. Owner keys also get the invoice count. Worth calling first in any session.

    No arguments

  • ask_brainSearch the company brain

    The passages that best match the question, each with the kind of source it came from. Search is hybrid: vector similarity, full text and recency fused together. A member key gets results from threads, messages, documents, meetings and tasks only.

    question (2 to 500 characters), limit (1 to 20, default 8)

  • upcoming_meetingsUpcoming meetings

    Meetings starting between now and the end of the window, with title, start, end and which source they came from. Up to 50. Calendar events appear once Google Calendar is connected.

    days (1 to 60, default 7)

  • recent_meetingsRecent meetings

    The most recent calls Castan recorded, newest first, with the recap text when one exists, trimmed to 2000 characters.

    limit (1 to 25, default 10)

  • customersCustomers and companies

    Companies the workspace knows, up to 200. An owner key also gets the open receivable total and the overdue invoice count for each. A member key gets names and domains only.

    No arguments

  • work_in_progressWork in progress

    Active projects with their outcome and every task with its status, plus live checklists with every item, each with a done count against a total.

    No arguments

  • open_receivablesOpen receivablesOwner only

    Unpaid invoices, soonest due first, up to 100: invoice number, customer, amount, due date, and whether it is already overdue.

    No arguments

  • finance_summaryFinance summaryOwner only

    For the period: payments received with count and total, invoices issued with count and total, and open receivables with count and total. Every number comes from stored rows. Nothing is estimated or projected.

    period (30d, 90d or ytd, default 30d)

Connecting a client

Claude Code

One command
claude mcp add --transport http castan https://castan.ai/api/mcp \
  --header "Authorization: Bearer ck_your_key_here"

Or check it into a project, in .mcp.json at the repository root:

.mcp.json
{
  "mcpServers": {
    "castan": {
      "type": "http",
      "url": "https://castan.ai/api/mcp",
      "headers": {
        "Authorization": "Bearer ck_your_key_here"
      }
    }
  }
}

Claude Code expands ${CASTAN_API_KEY} from your environment, so writing that in place of the key keeps the file safe to commit and the key in your shell profile.

Cursor

Put this in .cursor/mcp.json in the project, or in ~/.cursor/mcp.json for every project:

.cursor/mcp.json
{
  "mcpServers": {
    "castan": {
      "url": "https://castan.ai/api/mcp",
      "headers": {
        "Authorization": "Bearer ${env:CASTAN_API_KEY}"
      }
    }
  }
}

${env:CASTAN_API_KEY} reads the key from the environment so it does not sit in a file that gets committed. A literal Bearer ck_... works too. Cursor uses that syntax for environment variables, and remote servers there take no type field.

Any other client

Point it at https://castan.ai/api/mcp, choose streamable HTTP as the transport, and set a static Authorization: Bearer ck_... header. Nothing else is needed: no session id, no callback URL, no client registration.

Checking it works

In Claude Code, run /mcp. The castan server should be listed as connected. Then ask the assistant to call the workspace tool: the answer opens with the name of the workspace the key reads, lists the connected sources with their sync state, and counts what is indexed.

From a terminal, the transport requires an Accept header that names both JSON and the event stream type, even though the answer comes back as JSON.

A tool list, with a key
curl -s https://castan.ai/api/mcp \
  -H "Authorization: Bearer ck_your_key_here" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

A working key returns the tool list, and so does a request with no key at all. Swap tools/list for a tools/call and the key starts to matter: a missing or revoked key returns HTTP 401 there.

When it does not work

The assistant says it found nothing. Ask it to call the workspace tool. That names the workspace the key opens, lists the connected sources with their sync state, and counts what is indexed. Most reports of an empty brain are either a workspace with no connected source yet or a first sync that has not finished.

It is reading the wrong company. A key is bound to the workspace it was created in. Create a key while signed in to the workspace you meant, and revoke the old one.

Finance questions come back empty and the money tools are missing. The key has member access. Create an owner key if the assistant should see invoices and payments.

HTTP 401. The header is missing, malformed, or the key has been revoked. The value must be the whole key including the ck_ prefix, after the word Bearer and one space. The reply carries a WWW-Authenticate: Bearer realm="castan" header and a short JSON body saying what to send. A 401 on initialize or tools/list means something else: those answer without a key, so the request is not the shape it looks like. A batch that carries a tools/call beside a tools/list is refused whole.

HTTP 429. Only the keyless path is limited, at 60 requests an hour per calling address. Send a key, or wait the number of seconds in the Retry-After header.

HTTP 406. The client did not send an Accept header naming both application/json and text/event-stream. Every real MCP client does this; a hand written curl needs it added.

A JSON-RPC error saying Castan could not answer. That is a fault on the Castan side, not a problem with the key. It is safe to retry.

What this server does not do

  • No OAuth. Authentication is the static bearer key described above. The MCP specification treats authorization as optional, and the clients above accept a static header, so this connects today. There is no protected resource metadata document and no authorization server.
  • No cross-origin headers on /api/mcp, so a browser based client running on another origin cannot call the endpoint. Command line and desktop clients are unaffected. The server card does carry them, since a directory has to be able to read it from its own page.
  • No resources and no prompts. Tools only.
  • No writes, no subscriptions, no notifications, no elicitation.
  • No streaming. Answers arrive as one JSON response.

Where the data goes

Nowhere new. The server reads the workspace and answers the caller, and sends nothing outward. Keys are stored as SHA-256 hashes, so the plaintext key exists only in the client that holds it. Creation and revocation are both written to the workspace audit log, and each request stamps when the key was last used, which the owner sees in Settings. The rest of how Castan handles company data is on the security page and in the privacy policy. Questions about the connector go to hello@castan.ai.

Operator
OCULI OMNIUM SRL, societate cu răspundere limitată (SRL)
Registration
CUI 52198491 · Registrul Comerțului J2025054313009 · capital social 200 lei
Registered office
Intr. Gheorghe Simionescu 19 Ap. B26
VAT
The company is not registered for VAT (small-enterprise exemption, art. 310 Cod fiscal), so prices are final and include no VAT.
Licences
None required for this activity. The service is delivered online; there are no delivery costs.
Consumers
Complaints go to hello@castan.ai first. If we cannot settle one, you may turn to ANPC (Bd. Aviatorilor 72, București, 021 9551, anpc.ro) and to its alternative dispute resolution service, SAL: reclamatiisal.anpc.ro.
Businesses
Business customers are not consumers; the consumer remedies and the right of withdrawal do not apply to them.
ANPC, Soluționarea alternativă a litigiilor

Terms · Privacy · Security